NOTE: OUTDATED

Outline of CPT Written response

3 a. 3.a.i. The program provides a game helps create a people know who has played games and when they have played so that they can also see who plays frequently or wins the most.

3.a.ii. The function of the program is to to all the past pong games from most recent to oldest.

3.a.iii. The input will be the usernames of the two players, the score each player earned, the result of each player, and the date the game was played. The output will be the json data that can later be used to create a table sorted from most recent to oldest.

3.b.i.

game1 = Pong('AAA', 'BBB', '1', '5', 'Loss', 'Win', date(2023, 1, 22))
game2 = Pong('AAB', 'ABC', '2', '5', 'Loss', 'Win', date(2023, 1, 21))
game3 = Pong('AAC', 'GHI', '5', '4', 'Win', 'Loss', date(2023, 1, 20))
game4 = Pong('AAD', 'FGH', '5', '1', 'Win', 'Loss', date(2023, 1, 19))
game5 = Pong('AAE', 'TYU', '3','5', 'Loss', 'Win', date(2023, 1, 22))

games = [game1, game2, game3, game4, game5]

3.b.ii.

"""Builds sample user/note(s) data"""
for game in games:
    try:
        user.create()
    except IntegrityError:
        '''fails with bad or duplicate data'''
        db.session.remove()
        print(f"Records exist, duplicate email, or error in {game.user1} and/or {game.user2}")

3.b.iii. The variable being used to store the list is games

3.b.iv. The data that my list contains represents a game that was played in pong.

3.b.v. The dictionary in the variable body helps to create separate, distinct packets of information specifically for each game played. Without the use of this dictionary, the database would not be able to distinguish which game users participate in. This can make the program code harder to create as there would have to be a separate, more complex algorithm which manually sorts the data already present in the database.

3.c.i.

class PongAPI:
    class PongCreate(Resource):    
        def post(self):
            data = request.get_json()

            user1 = data.get('user1')
            if user1 is None or len(user1) != 3:
                return {'message': f'username 1 is missing or longer than 3 characters'}, 210
                
            user2 = data.get('user2')
            if user2 is None or len(user2) != 3:
                return {'message': f'username 2 is missing or longer than 3 characters'}, 210
            
            # Change later to exclude negative scores
            score1 = data.get('score1')
            if score1 is None or len(score1) <= 0:
                return {'message': f'Score 1 does not exist, is missing, or is invalid'}, 210 

            score2 = data.get('score2')
            if score2 is None or len(score2) <= 0:
                return {'message': f'Score 2 does not exist, is missing, or is invalid'}, 210 
                
            result1 = data.get('result1')
            if result1 is None:
                return {'message': f'Game result does not exist or is missing'}, 210 
            
            result2 = data.get('result2')
            if result2 is None:
                return {'message': f'Game result does not exist or is missing'}, 210 
            
            scoreDate = data.get('scoreDate')

            pongProfile = Pong(user1=user1, user2=user2, score1=score1, score2=score2, result1=result1, result2=result2)

            if scoreDate is not None:
                try:
                    pongProfile.scoreDate = datetime.strptime(scoreDate, '%m-%d-%Y').date()
                except:
                    return {'message': f'Date obtained score format error {scoreDate}, must be mm-dd-yyyy'}, 210
            
            user = pongProfile.create()
            if user:
                return jsonify(user.make_dict())
            return {'message': f'Processed {user1} and/or {user2}, either a format error or Usernames {user1} and/or {user2} is duplicate'}, 210

3.c.ii.

  function read_users() {
    // prepare fetch options
    const read_options = {
      method: 'GET', // *GET, POST, PUT, DELETE, etc.
      mode: 'cors', // no-cors, *cors, same-origin
      cache: 'default', // *default, no-cache, reload, force-cache, only-if-cached
      credentials: 'omit', // include, *same-origin, omit
      headers: {
        'Content-Type': 'application/json'
      },
    };

    // fetch the data from API
    fetch(read_fetch, read_options)
      // response is a RESTful "promise" on any successful fetch
      .then(response => {
        // check for response errors
        if (response.status !== 200) {
          const errorMsg = 'Database read error: ' + response.status;
          console.log(errorMsg);
          const tr = document.createElement("tr");
          const td = document.createElement("td");
          td.innerHTML = errorMsg;
          tr.appendChild(td);
          resultContainer.appendChild(tr);
          return;
        }
        // valid response will have json data
        response.json().then(data => {
          console.log(data);
          data.sort(function(a, b) {
            return new Date(b.scoreDate) - new Date(a.scoreDate);
          });
          for (let i = 0; i < data.length; i++) {
            const row = data[i];
            console.log(row);
            add_row(row);
          }
        })
      })
      // catch fetch errors (ie ACCESS to server blocked)
      .catch(err => {
        console.error(err);
        const tr = document.createElement("tr");
        const td = document.createElement("td");
        td.innerHTML = err;
        tr.appendChild(td);
        resultContainer.appendChild(tr);
      });
  }


  function add_row(data) {
    const tr = document.createElement("tr");
    const user1 = document.createElement("td");
    const user2 = document.createElement("td");
    const score1 = document.createElement("td");
    const score2 = document.createElement("td");
    const result1 = document.createElement("td");
    const result2 = document.createElement("td");
    const scoreDate = document.createElement("td");

  
    // obtain data that is specific to the API
    user1.innerHTML = data.user1; 
    user2.innerHTML = data.user2; 
    score1.innerHTML = data.score1;
    score2.innerHTML = data.score2;
    result1.innerHTML = data.result1;
    result2.innerHTML = data.result2;
    scoreDate.innerHTML = data.scoreDate;

    // add HTML to container
    tr.appendChild(user1);
    tr.appendChild(user2);
    tr.appendChild(score1);
    tr.appendChild(score2);
    tr.appendChild(result1);
    tr.appendChild(result2);
    tr.appendChild(scoreDate);

    resultContainer.appendChild(tr);
  }

3.c.iii. The procedure add_row() adds a row on the table of the game history, and displays the user1, user2, score1, score2, result1, result2, and date based on the user’s inputs and the data from the API or the pong game. This helps to display the data from user inputs and other inputs onto the game history so that other users are able to see the past games.

3.c.iv. The algorithm fetches the API using its URL to execute the GET method. It then checks that a successful fetch will be guaranteed, and if it is, then a response is carried out. An if statement is used to check if the response has an error with reading the database. If there is an error, an error message is displayed on the table of the game history, and the entire function fetching the API is stopped. However, if there is no error, the algorithm proceeds to check that the response contains JSON data. If it does contain JSON data, the algorithm proceeds to sort the users, where the most recent game is displayed first and the oldest game is displayed last. Finally, the algorithm checks for any fetch errors, and if there is a fetch error, an error message is displayed onto the table of the game history.

3.d.i. First Call: The first call is when the user clicks submit to submit information from the completed game.

Second Call: The second call is when the user clicks on the game history page, which calls the read_games function that displays the past games from most recent to oldest

3.d.ii Condition(s) tested by first call: The first call checks the errors and successfully determines that there are no errors with fetching the data. If there are no errors, the API will add the game to the database.

Condition(s) tested by second call: The second call checks fetch errors using the .catch() command. Since if no errors are found, it will use the database and the arguments of the data to create the table.

3.d.iii Results of first call: The first call displays that the game has successfully been added to the database games

Results of the second call: The page shows sorts the database from the newest game recorded to the oldest.