Category: Blog

  • Instruction-Counter

    Instruction-Counter

    In this project, ınstruction numbers from a c program are counted with pin and c++.

    The Output:

    Total Count (Task1) 721299

    Task2

    Branch Count: 68083

    Memory Count: 340091

    Arithmetic Count: 313125

    Task3

    Freqquency Of RAX 1498

    Freqquency Of RBX 388

    Freqquency Of RCX 477

    Freqquency Of RDX 713

    Freqquency Of RSI 556

    Freqquency Of RDI 681

    Freqquency Of RSP 2403

    Freqquency Of RBP 308

    Freqquency Of R8 156

    Freqquency Of R9 115

    Freqquency Of R10 162

    Freqquency Of R11 70

    Freqquency Of R12 235

    Freqquency Of R13 188

    Freqquency Of R14 188

    Freqquency Of R15 153

    General Explanation:

    Firstly, I downloaded matmul.c, matmul.h and matmul.sh files from the link. After that I downloaded the pin that a binary instrumentation tool. I customized some settings for pin with the following lines:

    set env INTEL_JIT_PROFILER32 /ia32/bin/libpinjitprofiling.so

    set env INTEL_JIT_PROFILER64 /intel64/bin/libpinjitprofiling.so

    make all TARGET=intel64

    Then, I opened new folder in pin/source/tools folder and run the c code in this folder. Also I put my cpp codes for pin instrumentation in this folder. After I run the matmul code , I used the output file to count instructions.

    TASK -1:

    In task 1, the total number of instructions were wanted. Therefore, I used a manual example from pin files which is inscount0.cpp. I used to following methods to calculate total numbers of instructions.

    VOID dototalcount() { total++; }

    This method just changing the number of total variable.

    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)dototalcount, IARG_END);

    This method calls instructions and dototalcount method.

    Also, PIN is a CISC architecture but it tries to use advantages of RISC architecture.

    TASK-2:

    In this task, the number of instructions wanted according to their types. I just used if conditions to find memory and branch instructions like following lines:

    if (INS_IsBranch(ins)) {

    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)dobranchcount, IARG_END);

    }

    for (UINT32 memOp = 0; memOp < memOperands; memOp++)

    {

    if (INS_MemoryOperandIsWritten(ins,memOp) || INS_MemoryOperandIsRead(ins,memOp)) {

    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)domemcount, IARG_END);

    }

    }

    However, in the memory instructions I checked if an instruction is written to memory or read from memory. If it is one of them I changed counter by 1.

    Also, to calculate the arithmetic instructions I used this formula:

    total-(branchcount+memcount)

    TASK-3:

    In this task the frequencies of usage of register in pin were asked. I just used again if conditions to calculate this for each register with different counters(c,c1,c2,c3,…….).

    if (INS_RegWContain(ins,REG_RBX)) {

    c2++;

    }

    Visit original content creator repository
    https://github.com/alprn42/Instruction-Counter

  • aws-rotate-iam-key

    aws-rotate-iam-key

    This module will rotate the aws iam api key for supplied {{iam_username}} variable set for Windows or Linux. It uses the awscli commands to create a new key, and then updates the key on the server. A requirement is the {{iam_username}} only has 1 active key, or the 2nd key is set to INACTIVE. It creates a new key when there is only 1. If there are 2 active keys (max allowed on aws account) the playbook will fail. The playbook will delete an inactive key to make room on the account supplied in {{iam_username}}.

    • Windows credentials location: C:\Users\{{aws_cli_user}}\.aws
    • Linux credentials are determined from the ENV of {{aws_cli_user}} and stored in the home directory of that user.

    Requirements

    The awscli needs to be configured on the Ansible server running the playbook. Ensure that you have correct permissions to reset and generate new IAM api keys from the account that runs the Ansible playbook.

    Role Variables

    Please define the following variables in host_vars for your server.

    • iam_username
      • AWS account that is has an IAM API key generated.
    • aws_cli_user
      • The account on the OS that has aws CLI configured.
    • aws_region
      • AWS region in use, I.E. us-east-1
    • aws_cloudfront
      • Enter true/false if you need access to AWS Cloudfront cli commands.
    • notify_service (OPTIONAL)
      • Only needed if you need to restart a service after key is rotated.
    • set_environment_vars (OPTIONAL)
      • Set to Yes or No. AWS API key and secret will be set in environment variables for the server. (potential security risk)

    Example host_vars file:

    iam_username: bouncingsoles  
    aws_cli_user: user1
    aws_region: us-east-1
    aws_cloudfront: true
    ##Optional
    notify_service: httpd
    set_environment_vars: "Yes"

    Dependencies

    • aws-cli
      — Need to be configured on the ansible server running the playbook.
      — Correct permissions to reset and generate new IAM api keys.

    Example Playbook

    - name: Rotate keys used in AWS for hosts that use api keys.
      hosts: xxxx
      roles:
         - bouncingsoles.aws-rotate-iam-key

    License

    BSD

    Author Information

    Patrick Durante

    Visit original content creator repository
    https://github.com/bouncingsoles/aws-rotate-iam-key

  • data-block-extract

    HTML5 data block extractor

    Did you know you can embed “raw” data into an HTML <script> tag? The HTML5
    spec calls them data blocks.

    They look like this…

    <script type="application/ld+json">
    {
      "@context": "http://schema.org/",
      "type": "SoftwareApplication",
      "name": "data block extractor",
      "alternateName": "data-block-extractor"
    }
    </script>

    This little command-line script takes a URL or a file, and extracts the content
    from any data blocks found in that file.

    Currently, it just dumps them to standard out and only looks for
    application/ld+json, but it’s a start anyway!

    Install

    For now, you have to npm i -g from inside a clone of this repository. At
    somepoint, we’ll get this up on NPM for easier re-use.

    However, once you’ve done that, you can run data-block-extractor anywhere to
    use this awesomeness!

    Usage

    $ data-block-extract http://bestbuy.com/

    Three results are (currently) found at BestBuy, which
    looks like this in the output:

    {"@context" : "http://schema.org","@type" : "WebSite","name" : "Best Buy","url" : "http://www.bestbuy.com/"}
    
    {"@context": "http://schema.org","@type": "Organization","name": "Best Buy","url": "http://www.bestbuy.com/","sameAs": ["http://www.facebook.com/bestbuy","https://twitter.com/BestBuy","https://plus.google.com/+BestBuy","https://www.instagram.com/bestbuy/","https://www.youtube.com/user/bestbuy","https://www.linkedin.com/company/best-buy","https://pinterest.com/BestBuy"],"contactPoint": [{"@type": "ContactPoint","telephone": "+1-888-237-8289","contactType": "customer service","contactOption": "TollFree","availableLanguage": ["English","Spanish"]}, {"@type": "ContactPoint","telephone": "+1-888-574-1301","contactType": "credit card support","contactOption": "TollFree","availableLanguage": ["English","Spanish"]}]}
    
    {"@context":"http://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"https://www-ssl.bestbuy.com/","name":"Best Buy"}}]}
    

    At the moment there is no additional parsing, but that’s coming!

    License

    MIT

    Visit original content creator repository
    https://github.com/WileyLabs/data-block-extract

  • SportsCaster

    SportsCaster

    Get footy notifications about your favorite teams (via sms message)


    STEPS

    1. TWILIO

    This script uses TWILIO, a free sms-messaging gateway. Visit twilio.com, create an account, and get a twilio phone number! Once this is done, copy the twilio phone number, ACCOUNT SID, and AUTH TOKEN into the sportsCaster.py script.

    2. ADD YOUR PHONE NUMBER

    Add all phone numbers that you wish to receive footy notifications to the TARGET_PHONE list.

    3. GET LEAGUE AND CLUB NAME

    1. Visit https://www.espn.com/soccer/scoreboard
    2. Hit ctrl+u to see the source code
    3. Search for ‘slug’ with ctrl+f to find leagues
    4. Look for a league that you wish to add the the LEAGUE_CLUBS dictionary by searching through the instances of ‘slug’
    5. Add your league’s slug value to the dictionary
    6. Search for ‘shortDisplayName’ with ctrl+f to find clubs
    7. Add club’s shortDisplayName value to their appropriate leagues list

    4. (OPTIONAL) FOR PI USERS

    Automate notifications by using crontab. On the pi cmd window enter ‘crontab -e’ and at the bottom of the list that appears enter the time and date to execute a command. The format for adding items is as follows:

    min hour day month day-of-the-week command
    

    For example:

    0 9 * * * sudo python3 sportsCaster.py      # notifies you every day at 9:00 am
    

    MESSAGES

    MORNING

    In the morning the scripts sends the fixtures for the day and the time the games occur.

    AFTERNOON

    In the afternoon the script sends results of the games of that day

    Visit original content creator repository
    https://github.com/alfredogonz97/SportsCaster

  • Restful-API-Laravel

    Laravel Logo

    Build Status Total Downloads Latest Stable Version License

    About Laravel

    Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:

    Laravel is accessible, powerful, and provides tools required for large, robust applications.

    Learning Laravel

    Laravel has the most extensive and thorough documentation and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.

    You may also try the Laravel Bootcamp, where you will be guided through building a modern Laravel application from scratch.

    If you don’t feel like reading, Laracasts can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.

    Laravel Sponsors

    We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel Partners program.

    Premium Partners

    Contributing

    Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the Laravel documentation.

    Code of Conduct

    In order to ensure that the Laravel community is welcoming to all, please review and abide by the Code of Conduct.

    Security Vulnerabilities

    If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via taylor@laravel.com. All security vulnerabilities will be promptly addressed.

    License

    The Laravel framework is open-sourced software licensed under the MIT license.

    Visit original content creator repository https://github.com/dzulfiqar890/Restful-API-Laravel
  • arm-js-library

    arm-js-logo

    cicd-badge-logo npm-badge-logo license-badge-logo

    Table of Contents

    Overview

    ARM (API Resource Manager) is a JavaScript library designed to centralize data management and simplify interactions with APIs. By providing a structured approach to handling and storing fetched data, ARM promotes efficient and flexible data usage throughout your application.

    Core Functionalities

    • Centralized Data Storage: Organizes fetched data into easily accessible collections, acting as a single source of truth for your application’s data.
    • API Interactions: Manages API requests and responses, providing methods for common HTTP operations (GET, POST, PUT, DELETE).
    • Caching: Optimizes performance by caching frequently accessed data, reducing API calls and improving response times.
    • Request Management: Tracks ongoing requests to prevent redundancy and manages their state.
    • Utility Functions: Offers helper functions for data manipulation, filtering, sorting, and other common operations.
    • Root Scope: An object that can be used to store and manage global state.

    Key Features

    • Collections: Stores fetched data in collections for efficient retrieval and management.
    • Record Management: Provides methods to create, update, delete, and retrieve individual records within collections.
    • Reactive Data: Employs observable patterns (likely through a library like Mobx) to enable real-time updates and dependency tracking.
    • Asynchronous Operations: Handles API interactions asynchronously using Promises for non-blocking operations.
    • Error Handling: Manages errors gracefully and provides informative feedback.
    • Configurability: Allows customization of API endpoints, headers, and request behavior.
    • Extensibility: Can be integrated with other libraries and frameworks to fit various application architectures.

    Benefits

    • Centralized Data Access: Provides a single source of truth for application data, ensuring consistency and reducing data duplication.
    • Improved Performance: Caching and optimized request management enhance application speed.
    • Enhanced Developer Experience: Simplifies data management and reduces boilerplate code.
    • Flexibility: Can be used across different components and parts of an application.
    • Maintainability: Promotes code organization and reduces potential inconsistencies.

    By centralizing data management and offering flexible access to it, ARM empowers developers to build more efficient, scalable, and maintainable applications.

    Basic Usage

    // Example usage in ReactJS
    
    import { observer } from 'mobx-react'
    import { ARM } from '@components/arm-config-wrapper'
    
    const App = observer(() => {
      const { isLoading, isError, data: address } = ARM.findRecord(
        'addresses',
        123456,
        { include: 'user' },
        { alias: 'customerAddress' }
      )
    
      return (
        <div className="App">
          {isLoading && <span>Loading...</span>}
          {!isLoading && (
            <div className="form">
              <label>Address1 </label>
              <input
                value={address.get('attributes.address1')}
                onChange={(event) =>
                  address.set('attributes.address1', event.target.value)
                }
              />
              &nbsp;
              <button
                onClick={() => {
                  address
                    .save()
                    .then((result) => console.log(result))
                    .catch((error) => console.log(error))
                }}
              >
                {address.get('isLoading') ? 'Saving' : 'Save'}
              </button>
            </div>
          )}
        </div>
      )
    })
    
    export default App

    Installation

    npm install arm-js-library --save
    

    Dependency Packages

    npm install mobx-react --save
    

    Initialization and Configuration

    Initialization

    Create arm-config-wrapper component that will store the new ARM instance.

    • Store it on component wrapper src/components/arm-config-wrapper/index.js here’s an example
      // Tag component wrapper as client for NextJS specific only
      'use client'
      
      // Create a new instance of ARM
      import ApiResourceManager from 'arm-js-library'
      
      // Create an array of collections to initialize
      const collections = ['addresses', 'users']
      
      // Export new instance of ARM for later utilization
      export const ARM = new ApiResourceManager(collections)
      
      // Main config wrapper
      const ARMConfigWrapper = ({ children }) => {
        return <>{children}</>
      }
      
      export default ARMConfigWrapper
    • For NextJS project, wrap root layout src/app/layout.js with arm-config-wrapper component here’s an example
      import dynamic from 'next/dynamic'
      
      const ARMConfigWrapper = dynamic(
        () => import('../components/arm-config-wrapper'),
        { ssr: false }
      )
      
      export default function RootLayout({ children }) {
        return (
          <html lang="en">
            <body>
              <ARMConfigWrapper>{children}</ARMConfigWrapper>
            </body>
          </html>
        )
      }
    • For non NextJS project, wrap root app src/index.js with arm-config-wrapper component.
      import ARMConfigWrapper from '@components/arm-config-wrapper'
      import ReactDOM from 'react-dom/client'
      import App from './App'
      
      const root = ReactDOM.createRoot(document.getElementById('root'))
      root.render(
        <ARMConfigWrapper>
          <App />
        </ARMConfigWrapper>
      )

    Configuration

    Configure stored ARM instance from where you stored it, to be able to use it on your application.

    Required configurations

    • setHost(value)
      // Set API endpoint host URL
      // By default host is set to window.location.origin
      ARM.setHost('https://www.test-demo.com')
    • setHeadersCommon(key, value)
      // Set common request headers required on calling API endpoints
      // ie. Authoization, Content-Type, etc.
      ARM.setHeadersCommon('Authorization', `${token}`)
      ARM.setHeadersCommon('Content-Type', 'application/vnd.api+json')
      ARM.setHeadersCommon('X-Client-Platform', 'Web')
    • setNamespace(value)
      // Set namespace for API endpoint host URL
      // By default namespace is set to 'api/v1'
      ARM.setNamespace('api/v1')

    Optional configurations

    • setGlobal(value)
      // Set ARM instace to global
      // This will make ARM instance available on browser window object via window.ARM
      // Example:
      //  console.log(window.ARM)
      ARM.setGlobal()
    • setPayloadIncludeReference(value)
      // Set payload included reference key
      // Payload included reference key serve as mapper to determine what collection
      // the data received belongs to
      // Example:
      //  {
      //    data: [...],
      //    included: [ { id: 1, type: 'addresses' } ]
      //  }
      ARM.setPayloadIncludeReference('type')

    Utilization

    To be able to use ARM features. You have to import the stored ARM instance from arm-config-wrapper component.

    // ARM instance is stored on src/components/arm-config-wrapper/index.js
    import { ARM } from '@components/arm-config-wrapper'

    Request functions from server


    • query(resource, params, config)
      • Querying multiple records from the server.
      • Support query params. – required
      • Support config. – optional
      ARM.query(
        'addresses',
        {
          sort: '-id',
          include: 'user',
        },
        {
          alias: 'customerAddresses',
        }
      )
    • queryRecord(resource, params, config)
      • Querying for a single record from the server.
      • Support query params. – required
      • Support config. – optional
      ARM.queryRecord(
        'addresses',
        {
          id: 123456,
          sort: '-id',
          include: 'user',
        },
        { alias: 'customerAddress' }
      )
    • findAll(resource, config)
      • Retrieving multiple records from the server.
      • Support config. – optional
      ARM.findAll('addresses', {
        alias: 'customerAddresses',
      })
    • findRecord(resource, id, params, config)
      • Retrieving single record from the server.
      • Params ID by default. – required
      • Support query params. – required
      • Support config. – optional
      ARM.findRecord(
        'addresses',
        123456,
        { include: 'user' },
        {
          alias: 'customerAddress',
        }
      )

    Passed Arguments: Request functions from server


        // Example: https://www.test-demo.com/api/v1/addresses/1?include=user
        ARM.findRecord('addresses', 123456,
          { 
            include: 'user' 
          },
          {
            skip: true,
            alias: 'customerAddress',
          }
        )
    • resource – String
      • https://www.test-demo.com/api/v1/ addresses /1?include=user
      • Endpoint resource name.
      • Serve as collection name defined on the collection intialization of ARM instance.
    • id – Number
      • https://www.test-demo.com/api/v1/addresses/ 1?include=user
      • Endpoint id parameter.
    • params – Object
      • https://www.test-demo.com/api/v1/addresses/1? include=user
      • Endpoint query string parameters.
    • config – Object
      • Contains request config such as (skip, alias, autoResolve, ignorePayload, override) which are currently available.
        {
          // Skip serve as request go signal to proceed 
          // if Request B has dependency on Request A
          skip: true,
      
          // Alias serve as identifier for the records obtain from the server.
          // Can be used anywhere in your application through ARM.getAlias('customerAddress')
          alias: 'customerAddress' ,
      
          // Auto resolve serve as flag if the request functions will return 
          // 1. Promise Function
          //  - To handle success and errors on manual resolve) if autoResolve is set to false
          // 2. Observable/Reactive Data
          //  - To handle success and errors on auto resolve) if autoResolve is set to true 
          // Note: autoResolve is only available on query, queryRecord, findAll, findRecord functions.
          // By default autoResolve is set to true.
          autoResolve: false,
      
          // Ignore payload serve as list of keys to be omitted on request payload.
          ignorePayload: ['attributes.address2', 'attributes.address1'],
      
          // Override serve as request override for the default configuration of axios current request.
          // Currently support host, namespace, path and headers for the meantime.
          // Example:
          // Before override: https://www.test-demo.com/api/v1/users/1
          // After override: https://www.another-test-demo.com/api/v2/update-users/1
          override: {
            host: 'https://www.another-test-demo.com',
            namespace: 'api/v2',
            path: `update-users/${user.get('id')}`,
            headers: {
              'X-Client-Platform': 'Symbian',
            }
          }
        }

    Returned Object: Request functions from server


    • isLoading – Boolean
      • Current loading state of the request.
      • By default set to true.
      • Set to true once the request is initiated and set to false once request is done.
    • isError – Boolean
      • Current error state of the request.
      • By default set to false.
      • Set to true if the request received/encountered an error and set to false if none.
    • isNew – Boolean
      • Identifier if the request is newly created.
      • By default set to true.
      • Set to true if the request is already initiated once and set to false once it is already intiated before. Request functions are built with optimization, it does not repeatedly executing API request. Since it is optimized, it can be override using skip from request configuration.
    • data – Array || Object
      • Contains the request returned payload.
      • By default has value of an empty array or object depending on the request function used.
    • error – Object || String
      • Contains the request returned error.
      • By default has value of a null.
    • included – Array
      • Contains the request returned payload property included.
      • Specifically for JSON API.
    • meta – Object
      • Contains the request returned payload property meta.
      • Specifically for JSON API.
    • reload – Function
      • Allows for re-execution of a request and automatic update of the request hash object and relevant collections.
    // Returned object data properties are observable
    // It will automatically update once the request is already done
    {
      isLoading: true,
      isError: false,
      isNew: true,
      data: [],
      error: null,
      included: [],
      meta: {},
      reload: function
    }

    Retrieve functions from collections


    • peekAll(collectionName)
      • Retrieving multiple records from collection.
      ARM.peekAll('addresses')
    • peekRecord(collectionName, collectionRecordId)
      • Retrieving single record from collection.
      • Params ID by default. – required
      ARM.peekRecord('addresses', 123456)
    • getCollection(collectionName)
      • Retrieving all records from collection.
      ARM.getCollection('addresses')
    • getAlias(collectionName, collectionFallbackRecord)
      • Retrieving records from aliased request results.
      • Support collectionFallbackRecord. – optional
      const addresses = ARM.getAlias('customerAddresses', [])
      
      ARM.findAll('addresses', { alias: 'customerAddresses' })
      
      <ul>
        {addresses.map((address, index) => (
          <li key={index}>{address.get('id')}</li>
        ))}
      </ul>

    Create collection record function


    • createRecord(collectionName, collectionRecord, collectionRecordRandomId)
      • Create new collection record.
      • By default collectionRecord params is set to empty object if omitted – required
      • By default collectionRecordRandomId params is set to true – optional
      // Usage #1
      // Can ommit collectionRecord on createRecord initialization
      const newAddress = ARM.createRecord('addresses')
      newAddress.set('attributes.kind', 'school')
      newAddress.set('attributes.label', 'My school')
      
      // Usage #2
      // Can ommit collectionRecord on createRecord initialization
      const newAddress = ARM.createRecord('addresses', {
        attributes: { kind: 'school', label: 'My school' }
      })
      
      // Persist collection record to server.
      // Will call POST /addresses
      newAddress.save()

    Remove collection record functions


    • unloadRecord(collectionRecord)
      • Remove record from collection only.
      // Collection record to be remove collection.
      const address = ARM.peekRecord('addresses', 123456)
      
      // This will remove the record from collection and will not
      // remove permanently from the server.
      ARM.unloadRecord(address)
    • clearCollection(collectionName)
      • Clears a specified collection and unloads related records from aliases and request hashes.
      ARM.clearCollection('addresses')

    Push collection record function


    • pushPayload(collectionName, collectionRecords)
      • Push raw collection record/records to respective collections.
      // Retrieve raw data with barebone ajax/fetch function.
      ARM.ajax({
        method: 'get',
        url: 'addresses/12345'
      }).then(results => {
        // Will add/update collection records.
        ARM.pushPayload('addresses', results.data.data)
      })

    Collection Records: Properties and Functions


    // Example response data from API
    // See available properties, getter and  setter functions and request functions below.
    {
      "id": 123456,
      "type": "addresses",
      "attributes": {
        "address1": "Test Address 1",
        "address2": "1718729541222",
        "kind": "office",
        "label": "Anabu Hills",
        "latitude": "14.394261",
        "longitude": "120.940783"
      }
    }
    • State Properties
      • isLoading – Boolean
        • Current loading state of the record.
        • By default set to false.
        • Set to true once request functions (save, reload, destroyRecord) are initiated and set to false once done.
        address.get('isLoading')
      • isError – Boolean
        • Current error state of the record.
        • By default set to false.
        • Set to true once request functions (save, reload, destroyRecord) received an error and set to false if none.
        address.get('isError')
      • isPristine – Boolean
        • Current pristine state of the record.
        • By default set to true.
        • Set to false if the record is modified and set to true once reverted.
        address.get('isPristine')
      • isDirty – Boolean
        • Current dirty state of the record.
        • By default set to false.
        • Set to true if the record is modified and set to false once reverted.
        address.get('isDirty')
    • Getter and Setter Functions
      • get(key)
        • Single property getter function.
        • Passed arguments:
          • key – String
        // Returned value 123456
        address.get('id') 
        
        // Returned value 'office'
        address.get('attributes.label') 
      • set(key, value)
        • Single property setter function.
        • Passed arguments:
          • key – String
          • value – Primitive
        // Returned value 'office'
        address.get('attributes.kind')
        
        // Set property label of attributes
        address.set('attributes.kind', 'school')
        
        // Returned value 'office'
        address.get('attributes.kind')
      • setProperties(value)
        • Multiple properties setter function.
        • Passed arguments:
          • value – Object
        // Returned value 'office'
        address.get('attributes.kind')
        // Returned value 'Anabu Hills'
        address.get('attributes.label')
        
        // Set properties label and kind of attributes
        address.setProperties({
          attributes: { kind: 'school', label: 'My School' }
        })
        
        // Returned value 'school'
        address.get('attributes.kind')
        // Returned value 'My School'
        address.get('attributes.label')
    • Request Functions
      • save(collectionConfig)
        • Persist collection record changes to server.
        • Create a new record to server only if it doesn’t already exist in the database.
          • Will call POST method: POST /addresses
        • Update existing record to server.
          • Will call PUT method: PUT /addresses/123456
        • Support collectionConfig. – optional
          • Available collectionConfig (skip, alias, autoResolve, ignorePayload, override)
        // Returned promise
        // Without collectionConfig
        address.save()
        
        // With collectionConfig
        address.save({ ignorePayload: ['attributes.address2'] })
      • reload()
        • Refresh collection record changes from server.
          • Will call GET method: GET /addresses/123456
        • Support collectionConfig. – optional
          • Available collectionConfig (skip, alias, autoResolve, ignorePayload, override)
        // Returned promise
        address.reload()
        
        // With collectionConfig
        address.reload({ 
           override: {
               namespace: 'api/v2',
           }
        })
      • destroyRecord(collectionConfig)
        • Remove collection record permanently from server.
          • Will call GET method: DELETE /addresses/123456
        • Support collectionConfig. – optional
          • Available collectionConfig (skip, alias, autoResolve, ignorePayload, override)
        // Returned promise
        // Without collectionConfig
        address.destroyRecord()
        
        // With collectionConfig
        address.destroyRecord({
          override: {
            host: 'https://ww7.test-demo.com',
            namespace: 'api/v2',
            path: `destroy-addresses/${address.get('id')}`,
          }
        })
      • getCollection(collectionName, collectionConfig)
        • Retrieve records from server automatically if async option value is set to true true on collectionConfig.
        • Retrieve records that are already loaded on collection if async option value is set to false on collectionConfig.
        • Passed arguments:
          • collectionName – String
          • collectionConfig – Object
            • referenceKey – String
              • Collection record property mapping.
            • async – Boolean
              • Flag for invoking request function on resolving not yet loaded records on collection.
            • filterBy – Object
              • Filter return collection records based on passed filter properties.
            • sortBy – Array
              • Sort returned collection records based on passed array of sort criteria.
            • config – Object
              • Contains request config such as (skip, alias, autoResolve, ignorePayload, override) which are currently available.
        // Get user record from the server but don't preload addresses records.
        const { isLoading, data: user } = ARM.findRecord(
          'users',
          123456,
          {
            // include: 'user'
          },
          { alias: 'currentUser' }
        )
        
        // The getCollection function will populate records from collection
        // and server depending on passed collectionConfig.
        {!isLoading && (
          <ul>
            {user
              .getCollection('addresses', {
                referenceKey: 'relationships.addresses.data',
                async: true,
                sortBy: ['id:desc'],
                filterBy: {
                  attributes: {
                    'label': 'Test'
                  }
                },
                override: {
                  namespace: 'api/v2',
                }
              })
              .map((address, index) => (
                <li key={index}>{address.get('id')}</li>
              ))}
          </ul>
        )}

    Root Scope Functions

    The root scope is an object that can be used to store and manage global state. The Root Scope Functions provide a way to manage and access it.

    • setRootScope(rootScopeProperty, rootScopeValue)

      • Sets a value on the root scope.
      • Passed arguments:
        • rootScopeProperty – String
        • rootScopeValue – Any
      // Set root scope property 'fullName' to 'John Doe'
      ARM.setRootScope('fullName', 'John Doe')
    • getRootScope(rootScopeProperty)

      • Retrieves a value from the root scope.
      • Passed arguments:
        • rootScopeProperty – String
      // Returns value 'John Doe'
      ARM.getRootScope('fullName')

    Utility Functions

    Collection of utility functions that leverage Lodash for common data manipulation tasks. These functions primarily focus on searching, filtering, sorting, and validating data within objects or arrays.

    Data Retrieval and Manipulation


    // Example response data from API
    const addresses = [
       {
         "id": 1,
         "attributes": {
           "kind": "office",
           "label": "My Office",
         }
       },
       {
         "id": 2,
         "attributes": {
           "kind": "school",
           "label": "My School",
         }
       },
       {
         "id": 3,
         "attributes": {
           "kind": "school",
           "label": "My Brother's School",
         }
       }
     ]
    • findBy(objects, findProperties)

      • Finds the first element in the given array of objects that satisfies the provided find properties.
      // Return record with id 1
      ARM.findBy(addresses, { id: 1 })
    • findIndexBy(objects, findIndexProperties)

      • Returns the index of the first element in the given array of objects that satisfies the provided find properties.
      // Return index number of record with id 1
      ARM.findIndexBy(addresses, {
        attributes: { kind: 'office' }
      })
    • filterBy(objects, filterProperties)

      • Creates a new array with all elements from the given array of objects that pass the filter test implemented by the provided filter properties.
      // Returns records with ids 2 and 3
      ARM.filterBy(addresses, {
        attributes: { kind: 'school' }
      })
    • uniqBy(objects, uniqByProperty)

      • Removes duplicate objects from an array based on a unique property.
      // Returns records with ids 1 and 2
      ARM.uniqBy(addresses, 'attributes.kind')
    • uniq(values)

      • Removes duplicate values from an array.
      // Returns array with 1,2,3
      ARM.uniq([1, 2, 2, 3, 3, 3])
    • groupBy(objects, groupByProperty)

      • Incorrectly uses uniqBy instead of grouping objects by the specified property.
      // Returns { school: [{ id: 2 }, { id: 3 }], office: [{ id: 1 }]} 
      ARM.groupBy(addresses, 'attributes.kind')
    • mapBy(objects, mapByProperty)

      • Maps an array of objects, extracting a specific property from each.
      // Returns ['office', 'school', 'school']
      ARM.mapBy(addresses, 'attributes.kind')
    • firstObject(objects)

      • Returns the first element from the given array of objects. If the array is empty, it returns undefined.
      // Return record with id 1
      ARM.firstObject(addresses)
    • lastObject(objects)

      • Returns the last element from the given array of objects. If the array is empty, it returns undefined.
      // Return record with id 3
      ARM.lastObject(addresses)
    • mergeObjects(objects, otherObjects)

      • Combines two arrays of objects into one, removing duplicates.
      ARM.mergeObjects(addresses, otherAddresses)
    • chunkObjects(objects, chunkSize)

      • Splits an array of objects into smaller arrays of a given size.
      ARM.chunkObjects(addresses, 2)
    • sortBy(objects, sortProperties)

      • Sorts the given array of objects by the specified sort properties.
      // Returns records order by ids 1,2,3
      ARM.sortBy(addresses, ['id:asc'])
      
      // Returns records order by ids 3,2,1
      ARM.sortBy(addresses, ['id:desc'])
    • ajax(config)

      • Axios instance under the hood with default ARM config.
      • Config accepts all properties that can be passed on axios.request config.
      // Return promise
      ARM.ajax({
        method: 'get',
        baseURL: 'https://other-api.test-demo.com',
        url: '/api/v1/addresses'
      })
      .then(results => console.log(results))
      .catch(errors => console.log(errors))

    Data Validation and Comparison

    • isEmpty(value)
      • Checks if a value is considered empty (null, undefined, empty string, empty array, or empty object).
      // Return boolean value
      ARM.isEmpty(value)
    • isPresent(value)
      • Returns the opposite of isEmpty.
      // Return boolean value
      ARM.isPresent(value)
    • isEqual(value, other)
      • Performs a deep comparison between two values to determine if they are equal.
      // Return boolean value
      ARM.isEqual(value, other)
    • isNumber(value)
      • Checks if a value is a number.
      // Return boolean value
      ARM.isNumber(value)
    • isNil(value)
      • Checks if a value is null or undefined.
      // Return boolean value
      ARM.isNil(value)
    • isNull(value)
      • Checks if a value is null.
      // Return boolean value
      ARM.isNull(value)
    • isGte(value, other)
      • Checks if the first value is greater than or equal to the second value.
      // Return boolean value
      ARM.isGte(value, other)
    • isGt(value, other)
      • Checks if the first value is greater than the second value.
      // Return boolean value
      ARM.isGt(value, other)
    • isLte(value, other)
      • Checks if the first value is less than or equal to the second value.
      // Return boolean value
      ARM.isLte(value, other)
    • isLt(value, other)
      • Checks if the first value is less than the second value.
      // Return boolean value
      ARM.isLt(value, other)
    Visit original content creator repository https://github.com/michaeljymsgutierrez/arm-js-library
  • voice-logger

    Voice Logger         Build status Open Source Love License

    Voice Logger is an application the uses Microsoft’s Kinect (V1) for recording voice logs that can then be exported to a ZIP file for storage or sharing. The idea was instead of putting comments in the code for myself to refer back to after a weekend of coding I could record voice logs instead. I used the Kinect as it was a prize I won in a recent university competition and I was excited to use it.

    Overview

    The application was written in C# and uses the Kinect SDK for voice recognition and NAudio for audio file creation. The UI is WPF based with help from the Metro UI framework which helps give the app modern styling to look more professional. The application uses the built in voice recognition technology found in the Kinect so interaction with the GUI isn’t necessary and instead commands can be issued via voice saving time and means the app doesn’t get in the way of coding.

    Features

    • Voice commands
    • Archive exporting
    • Modern UI

    Development

    • Screenshot feature
    • Microphone backup
    • MVVM refactor

    License

    Apache 2.0

    Visit original content creator repository https://github.com/william-taylor-projects/voice-logger
  • Kodi-PS4-Soundtheme

    PlayStation 4 Sound theme for Kodi

    Update: Seems like KnuxBoy04 on GitHub is trying to revive the PS4 theme. Please see: https://github.com/KnuxBoy04/skin.orbis

    Original Thread can be found here: https://forum.kodi.tv/showthread.php?tid=210625

    This theme was originally made by Toyota12303. Subsequently, the download links for the theme and sound theme hosted by Toyota12303 (hosted on Google Drive) was invalid.

    Later on, another user (SZNX) on the Kodi Forums uploaded a copy of the sound theme, but it didn’t seem to work properly.

    Delving into the XML file (sounds.xml), there were a few issues, causing the theme to not work. (It would work fine on Windows since windows does not care about case sensitivity of file names)

    I have corrected issues in the XML regarding the filenames and fixed the indentation to make it more readable. Tested it successfully on Kodi 21.1 (Omega)

    Installation Instructions

    • Download this repository and zip the resource.uisounds.PlayStation directory
      • The directory must be zipped with a .zip extension.
      • Use Store compression
    • Open Kodi and go to Settings -> File Manager
    • Select Install from ZIP file
    • Locate this zip file and follow on screen prompts.
    • Once installed, go to Settings -> System -> Audio
    • In that, you’ll find an option called UI Sounds or something similar
    • Select it and choose the PlayStation 4 UI Sounds

    Note

    • I don’t plan to update this by adding more sounds for different actions and whatnot. I may fix it if future versions of Kodi changes something.
    • Please do not request me to make new sound themes inspired from newer Xbox or PlayStation devices.

    Visit original content creator repository
    https://github.com/DAK404/Kodi-PS4-Soundtheme

  • MEffectUI

                                     Apache License
                               Version 2.0, January 2004
                            http://www.apache.org/licenses/
    
       TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
    
       1. Definitions.
    
          "License" shall mean the terms and conditions for use, reproduction,
          and distribution as defined by Sections 1 through 9 of this document.
    
          "Licensor" shall mean the copyright owner or entity authorized by
          the copyright owner that is granting the License.
    
          "Legal Entity" shall mean the union of the acting entity and all
          other entities that control, are controlled by, or are under common
          control with that entity. For the purposes of this definition,
          "control" means (i) the power, direct or indirect, to cause the
          direction or management of such entity, whether by contract or
          otherwise, or (ii) ownership of fifty percent (50%) or more of the
          outstanding shares, or (iii) beneficial ownership of such entity.
    
          "You" (or "Your") shall mean an individual or Legal Entity
          exercising permissions granted by this License.
    
          "Source" form shall mean the preferred form for making modifications,
          including but not limited to software source code, documentation
          source, and configuration files.
    
          "Object" form shall mean any form resulting from mechanical
          transformation or translation of a Source form, including but
          not limited to compiled object code, generated documentation,
          and conversions to other media types.
    
          "Work" shall mean the work of authorship, whether in Source or
          Object form, made available under the License, as indicated by a
          copyright notice that is included in or attached to the work
          (an example is provided in the Appendix below).
    
          "Derivative Works" shall mean any work, whether in Source or Object
          form, that is based on (or derived from) the Work and for which the
          editorial revisions, annotations, elaborations, or other modifications
          represent, as a whole, an original work of authorship. For the purposes
          of this License, Derivative Works shall not include works that remain
          separable from, or merely link (or bind by name) to the interfaces of,
          the Work and Derivative Works thereof.
    
          "Contribution" shall mean any work of authorship, including
          the original version of the Work and any modifications or additions
          to that Work or Derivative Works thereof, that is intentionally
          submitted to Licensor for inclusion in the Work by the copyright owner
          or by an individual or Legal Entity authorized to submit on behalf of
          the copyright owner. For the purposes of this definition, "submitted"
          means any form of electronic, verbal, or written communication sent
          to the Licensor or its representatives, including but not limited to
          communication on electronic mailing lists, source code control systems,
          and issue tracking systems that are managed by, or on behalf of, the
          Licensor for the purpose of discussing and improving the Work, but
          excluding communication that is conspicuously marked or otherwise
          designated in writing by the copyright owner as "Not a Contribution."
    
          "Contributor" shall mean Licensor and any individual or Legal Entity
          on behalf of whom a Contribution has been received by Licensor and
          subsequently incorporated within the Work.
    
       2. Grant of Copyright License. Subject to the terms and conditions of
          this License, each Contributor hereby grants to You a perpetual,
          worldwide, non-exclusive, no-charge, royalty-free, irrevocable
          copyright license to reproduce, prepare Derivative Works of,
          publicly display, publicly perform, sublicense, and distribute the
          Work and such Derivative Works in Source or Object form.
    
       3. Grant of Patent License. Subject to the terms and conditions of
          this License, each Contributor hereby grants to You a perpetual,
          worldwide, non-exclusive, no-charge, royalty-free, irrevocable
          (except as stated in this section) patent license to make, have made,
          use, offer to sell, sell, import, and otherwise transfer the Work,
          where such license applies only to those patent claims licensable
          by such Contributor that are necessarily infringed by their
          Contribution(s) alone or by combination of their Contribution(s)
          with the Work to which such Contribution(s) was submitted. If You
          institute patent litigation against any entity (including a
          cross-claim or counterclaim in a lawsuit) alleging that the Work
          or a Contribution incorporated within the Work constitutes direct
          or contributory patent infringement, then any patent licenses
          granted to You under this License for that Work shall terminate
          as of the date such litigation is filed.
    
       4. Redistribution. You may reproduce and distribute copies of the
          Work or Derivative Works thereof in any medium, with or without
          modifications, and in Source or Object form, provided that You
          meet the following conditions:
    
          (a) You must give any other recipients of the Work or
              Derivative Works a copy of this License; and
    
          (b) You must cause any modified files to carry prominent notices
              stating that You changed the files; and
    
          (c) You must retain, in the Source form of any Derivative Works
              that You distribute, all copyright, patent, trademark, and
              attribution notices from the Source form of the Work,
              excluding those notices that do not pertain to any part of
              the Derivative Works; and
    
          (d) If the Work includes a "NOTICE" text file as part of its
              distribution, then any Derivative Works that You distribute must
              include a readable copy of the attribution notices contained
              within such NOTICE file, excluding those notices that do not
              pertain to any part of the Derivative Works, in at least one
              of the following places: within a NOTICE text file distributed
              as part of the Derivative Works; within the Source form or
              documentation, if provided along with the Derivative Works; or,
              within a display generated by the Derivative Works, if and
              wherever such third-party notices normally appear. The contents
              of the NOTICE file are for informational purposes only and
              do not modify the License. You may add Your own attribution
              notices within Derivative Works that You distribute, alongside
              or as an addendum to the NOTICE text from the Work, provided
              that such additional attribution notices cannot be construed
              as modifying the License.
    
          You may add Your own copyright statement to Your modifications and
          may provide additional or different license terms and conditions
          for use, reproduction, or distribution of Your modifications, or
          for any such Derivative Works as a whole, provided Your use,
          reproduction, and distribution of the Work otherwise complies with
          the conditions stated in this License.
    
       5. Submission of Contributions. Unless You explicitly state otherwise,
          any Contribution intentionally submitted for inclusion in the Work
          by You to the Licensor shall be under the terms and conditions of
          this License, without any additional terms or conditions.
          Notwithstanding the above, nothing herein shall supersede or modify
          the terms of any separate license agreement you may have executed
          with Licensor regarding such Contributions.
    
       6. Trademarks. This License does not grant permission to use the trade
          names, trademarks, service marks, or product names of the Licensor,
          except as required for reasonable and customary use in describing the
          origin of the Work and reproducing the content of the NOTICE file.
    
       7. Disclaimer of Warranty. Unless required by applicable law or
          agreed to in writing, Licensor provides the Work (and each
          Contributor provides its Contributions) on an "AS IS" BASIS,
          WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
          implied, including, without limitation, any warranties or conditions
          of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
          PARTICULAR PURPOSE. You are solely responsible for determining the
          appropriateness of using or redistributing the Work and assume any
          risks associated with Your exercise of permissions under this License.
    
       8. Limitation of Liability. In no event and under no legal theory,
          whether in tort (including negligence), contract, or otherwise,
          unless required by applicable law (such as deliberate and grossly
          negligent acts) or agreed to in writing, shall any Contributor be
          liable to You for damages, including any direct, indirect, special,
          incidental, or consequential damages of any character arising as a
          result of this License or out of the use or inability to use the
          Work (including but not limited to damages for loss of goodwill,
          work stoppage, computer failure or malfunction, or any and all
          other commercial damages or losses), even if such Contributor
          has been advised of the possibility of such damages.
    
       9. Accepting Warranty or Additional Liability. While redistributing
          the Work or Derivative Works thereof, You may choose to offer,
          and charge a fee for, acceptance of support, warranty, indemnity,
          or other liability obligations and/or rights consistent with this
          License. However, in accepting such obligations, You may act only
          on Your own behalf and on Your sole responsibility, not on behalf
          of any other Contributor, and only if You agree to indemnify,
          defend, and hold each Contributor harmless for any liability
          incurred by, or claims asserted against, such Contributor by reason
          of your accepting any such warranty or additional liability.
    
       END OF TERMS AND CONDITIONS
    
       APPENDIX: How to apply the Apache License to your work.
    
          To apply the Apache License to your work, attach the following
          boilerplate notice, with the fields enclosed by brackets "[]"
          replaced with your own identifying information. (Don't include
          the brackets!)  The text should be enclosed in the appropriate
          comment syntax for the file format. We also recommend that a
          file or class name and description of purpose be included on the
          same "printed page" as the copyright notice for easier
          identification within third-party archives.
    
       Copyright [yyyy] [name of copyright owner]
    
       Licensed under the Apache License, Version 2.0 (the "License");
       you may not use this file except in compliance with the License.
       You may obtain a copy of the License at
    
           http://www.apache.org/licenses/LICENSE-2.0
    
       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.
    

    Visit original content creator repository
    https://github.com/MagmaZ3637/MEffectUI

  • WaitList

    Waitlist

    Check out our github pages at: https://sccapstone.github.io/WaitList/

    Application available at: http://uofscwaitlist.meteorapp.com

    Login for admin page

    email: redmonc2@email.sc.edu

    password: asdfasdf

    Demo of web application

    <iframe width=”560″ height=”315″ src=”https://github.com/SCCapstone/https://www.youtube.com/embed/VkXObYoXu38” frameborder=”0″ allowfullscreen></iframe>

    NOTIFICATION WHEN TESTING:

    Any number should be able to receive messages as long as the “opt in for text” box is checked on submission.

    If you need to test this application, please contact either either Cory Redmond (redmonc2@email.sc.edu) or Eddie Pace (paceea@email.sc.edu) member and we will deploy it. We do not keep it deployed all the time because we pay by the hour for it to be up

    For testing the “forgot password” function. Send us one of your emails and we will change the admin account email to match it. The password will remain “asdfasdf”. This web application only uses one account as per clients request.

    Home/log-in page

    This is the page that will be displayed for all students who wish to add themselves to the waitlist.

    Header

    Sign-in – drop menu to sign in to the admin account using the valid e-mail and password. a “forgot password” funciton is also provided to send to the valid admin e-mail account.

    Check Wait Time – A prompt to enter a phone number. If the phone number is currently attributed to a student in the wait list, it will return their current estimated remaining time.

    Example of the check wait time feature

    check_wait_time_modal 2

    Form Fields

    Name – (Required field)

    Phone Number – (Required field) – will only accept properly formatted numbers of 10-digits with no white-space or non-integer values.

    USC ID – (Required field) – USC ID is 9-digits/characters long.(foun on back of student ID cards).

    Reason for Visit – (Required field) – 3 drop-down options as per client request.

    Current Major – (Required field) – A list of all majors offered at UofSC-Columbia. This list will auto-complete and show a list of majors that match what you currenty have typed in for you to select.

    Intended Major – (Optional) – Same as Current Major.

    Comments – (Optional) – A text field to allow students to write anything they wish the Advisor to see before entering the appointment.

    Text service radio buttion – Checking this button to opt in for texting services will send text notifications to the phone number inputed in Phone Number field. This will first alert you that you have been added to the list. You can respond with either “Time” to get your current estimated remaining wait time or respond “Remove” to be removed form the waitlist.

    Submit – submits form to database

    The sign in form can be seen below:

    sign_up_form 2

    Admin Page

    This is the page for the administrator who will be advising during drop in hours.

    Header

    The header will be similar to that of the Sign up page, but will just contain the dropdown for signing out or changing the password while logged in as an admin. It will also have a download archive button

    Download Archive – This will download a csv file of every person saved in an archive when they are removed from the wait list.

    An example of a csv file downloaded is shown below:

    archive_example 2

    Features

    This page contains a table with all people currently on the wait list. It is sorted based off of who submitted their information first.

    This has each row show (Name, Phone number, USCID, Button selections, and current status).

    Expand button – This is the button with a plus sign on the left side of each row. If this button is pressed the row will expand and show a hidden row within the table that will show (Reason for visit, Current major, Intended major, and any submitted comments). This can be pressed again to hide the row.

    Button Selections

    Edit button – This button will bring a modal with a form similar to that of the sign in page (excludes comments and opt in for text radio button). It will populate the field with the selected students information and if any of that information is changed on submission it will then change in the table.

    Delete button – This will bring up a modal for confirmation of deleting the selected student from the wait list.

    Move button – This button is the one with a down arrow. This will move the specific student to the botton of the wait list and will reorder all wait times.

    Check-in button – This is a button that will change the current status field to “In Advisement” if pressed. If you wish to change the status back to “Waiting” double click on the check-in buttons (this is for accidental clicks on the check-in button). This is meant to be a check for the advisor to help keep track of who is in advisement if there are multiple advisors advising at one time.

    Check-out buttons – Basically the same thing as the delete button. It will bring up a modal for confirmation that the student has completed their advisement. If selected as done then the student will be removed from the list. This is meant to be a clarification button for the adminstrative user to try and reduce confusion of what to do once the person is done with advisement.

    An example of the Admin page can be seen below:

    admin_page 2

    Secret Page

    After the students sumbit the form, it will route to this secret page automatically. It will show the students their wait time on the screen. Also, the students can refer back to the page and check their wait time when they add their phone number after the “https://github.com/” in the URL. The wait time will update automatically.

    An example of the secret page is shown below:

    Header

    Sign-in – drop menu to sign in to the admin account using the valid e-mail and password. a “forgot password” funciton is also provided to send to the valid admin e-mail account.

    Check Wait Time – A prompt to enter a phone number. If the phone number is currently attributed to a student in the wait list, it will return their current estimated remaining time.

    Button selection

    Back to Sign Up Page Button – This button act as a home button for the students. It will route back to Sign Up page when a new student try to sumbit a form after others.

    secretpage 2

    Information on developers

    Cory Redmond, Eddie Pace, Ryan Morvay, Bao Li, Run Liang

    Visit original content creator repository https://github.com/SCCapstone/WaitList