CPT Requirements:
- Instructions for input (from the user, a device, an online data stream, or a file)
- Use of at least one list or other collection type to represent stored data
- At least one procedure that contributes to the intended purpose of the program (with the name, the return type, and one or more parameters)
- An algorithm including sequencing, selection, and iteration
- Instructions for output (tactile, audible, visual, or textual) that are based on inputs and the program’s functionality
Feature 1 - Preferences Page
Feature 2 - Favorite Books Page
Feature 3 - Reading Progress Tracker Page
Requirement 1: Instructions for Input (user)
Preferences
<button class="color-button" id="white">White</button>
<button class="color-button" id="black">Black</button>
<button class="color-button" id="changeMenu">Change Menu Color</button>
Cell In[1], line 1
<button class="color-button" id="white">White</button>
^
SyntaxError: invalid syntax
Favorite Books
<div class="container">
<input type="text" id="bookTitle" placeholder="Enter book title" />
<button class="button" onclick="addBook()">Add Book</button>
</div>
Reading Progress Tracker
<input type="text" id="bookTitle" placeholder="Book Title">
<input type="number" id="bookPercent" placeholder="Percent Read" min="0" max="100">
<button class="button" onclick="addBook()">Add Book</button>
<button class="button" onclick="fetchBooks()">Load Books</button>
In each of my pages, there are buttons to click which do different things such as change a color or prompt the user to enter more specifications inside a popup. In some of the pages, there are also empty text boxes already placed on the page for users to use with the buttons.
Requirement 2: Use of a Collection Type (dictionaries/lists)
Preferences
preferences = {
"menu": "red",
"text": "white"
}
Favorite Books
favorite_book_list = [
FavoriteBook(title="Hunger Games"),
FavoriteBook(title="Maze Runner"),
]
Reading Progress Tracker
book_progress_list = [
BookProgress(title="Hunger Games", percent_read=30.0),
BookProgress(title="Maze Runner", percent_read=50.0),
]
The data for each of my pages is stored inside of its own dictionary or list where it is repeatedly accessed to add, update, and delete information.
Requirement 3: Use of at least one procedure
Preferences
def update_preferences():
# Check if the request contains JSON
if request.is_json:
# Get the new preferences data from the JSON body
data = request.get_json()
# Update preferences dictionary with the new data
preferences.update(data)
# Return the updated preferences as a response
return jsonify(preferences), 200
else:
return jsonify({"error": "Request must be in JSON format"}), 400
Favorite Books
def get(self):
favorite_books = FavoriteBook.query.all()
return {"books": [book.read() for book in favorite_books]}, 200
Reading Progress Tracker
def put(self, book_progress_id):
data = request.get_json()
if not data or 'title' not in data:
return {'error': 'Title is required.'}, 400
book_progress = BookProgress.query.get(book_progress_id)
if not book_progress:
return {'error': 'Book progress not found.'}, 404
book_progress.title = data['title']
book_progress.percent_read = data.get('percent_read', book_progress.percent_read)
db.session.commit() # Save update to database
return book_progress.read(), 200
Each of the procedures in my features is defined, takes input, and returns data. While it may not seem like the function in Preferences is taking any parameters, it does use the JSON data and updates the dictionary with the preferences stored based on the data.
Requirement 4: Algorith with Sequencing, Selection, and Iteration
Preferences
def update_preferences():
# Check if the request contains JSON
if request.is_json:
# Get the new preferences data from the JSON body
data = request.get_json()
# Update preferences dictionary with the new data
preferences.update(data)
# Return the updated preferences as a response
return jsonify(preferences), 200
else:
return jsonify({"error": "Request must be in JSON format"}), 400
Favorite Books
function fetchBooks() {
fetch(apiUrl)
.then(response => response.json())
.then(data => {
const tableBody = document.getElementById('booksTable');
tableBody.innerHTML = '';
data.books.forEach(book => {
const row = `<tr>
<td>${book.id}</td>
<td>${book.title}</td>
<td>
<button class="button edit" onclick="editBook(${book.id}, '${book.title}')">Edit</button>
<button class="button delete" onclick="deleteBook(${book.id})">Delete</button>
</td>
</tr>`;
tableBody.innerHTML += row;
});
})
.catch(error => console.error('Error fetching books:', error));
}
Reading Progress Tracker
function addBook() {
const title = document.getElementById('bookTitle').value;
const percentRead = document.getElementById('bookPercent').value || 0;
if (!title) {
alert('Please enter a book title');
return;
}
fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, percent_read: parseFloat(percentRead) })
})
.then(response => response.json())
.then(data => {
if (data.error) {
alert(data.error);
} else {
fetchBooks();
}
})
.catch(error => console.error('Error adding book:', error));
}
Each of the above functions contain sequencing, as they all follow a guided set of steps. In these examples, Preferences and Reading Progress Tracker both have selection as well, as they contain if statements to select data and ensure that it is correct. Finally, Favorite Books has iteration as it contains the line data.books.forEach(parameters) which iterates through the data and does an action for each book.
Requirement 5: Instructions for Output (visual)
Preferences
let pColors = document.querySelectorAll('p');
pColors.forEach(p => {
p.style.color = data.text;
});
let menuItems = document.querySelectorAll('.menu-item');
menuItems.forEach(item => {
item.style.backgroundColor = data.menu;
});
Favorite Books
function editBook(bookId, currentTitle) {
const newTitle = prompt('Enter new book title:', currentTitle);
if (!newTitle || newTitle === currentTitle) return;
fetch(`${apiUrl}/${bookId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: newTitle })
})
.then(response => response.json())
.then(data => {
if (data.error) {
alert(data.error);
} else {
fetchBooks();
}
});
}
Reading Progress Tracker
function addBook() {
const title = document.getElementById('bookTitle').value;
const percentRead = document.getElementById('bookPercent').value || 0;
if (!title) {
alert('Please enter a book title');
return;
}
fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, percent_read: parseFloat(percentRead) })
})
.then(response => response.json())
.then(data => {
if (data.error) {
alert(data.error);
} else {
fetchBooks();
}
})
.catch(error => console.error('Error adding book:', error));
}
These code segments outline some of the outputs that users would get upon interacting with my features. For Preferences, when they use the buttons to change the colors of the page, the styling will be updated and they will see different colors based on their choice. For the other two, the user interaction will either change text that is already in a table or add new text to a table.
Overall
I believe that my features in the project all individually meet the CPT requirements as they contain all that is requested at a fairly advanced level.
N@tM Feedback
Most of the feedback that our group recieved was unfortunately not directed to my 5 contributions. However, I did recieve some comments.
Firstly, for my Reading Progress Tracker, Noah’s dad gave me the idea to take an input of (pages read)/(total pages) to make it easier for the users to track their progress. However, though I wanted to make this change, I could not figure out a way to make the database with the information stored take two values and also show a percentage based on those.
Other than that, most people said that the colors of the page and the design were good as a whole. They also said that we had a clean interface and that it was nice that the page loaded quickly.
PPR
Student-Developed Procedure
def get(self):
book_progress_list = BookProgress.query.all()
return {"books": [book.read() for book in book_progress_list]}, 200
def post(self):
data = request.get_json()
if not data or 'title' not in data:
return {'error': 'Title is required.'}, 400
These functions are defined with parameters and have sequencing, selection, and iteration
Student-Developed Procedure Being Called
const apiUrl = "https://litconnect.stu.nighthawkcodingsociety.com/api/book_progress";
function fetchBooks() {
fetch(apiUrl)
.then(response => response.json())
.then(data => {
const tableBody = document.getElementById('bookTableBody');
const bookSelect = document.getElementById('bookSelect');
tableBody.innerHTML = '';
bookSelect.innerHTML = ''; // Clear previous options
data.books.forEach(book => {
// Add to table
const row = `<tr>
<td>${book.title}</td>
<td>${book.percent_read}%</td>
<td><button class="button" onclick="deleteBook(${book.id})">Delete</button></td>
</tr>`;
tableBody.innerHTML += row;
// Add to select dropdown for update
const option = `<option value="${book.id}">${book.title}</option>`;
bookSelect.innerHTML += option;
});
})
.catch(error => console.error('Error fetching books:', error));
}
Frontend calling of my feature (book progress)
A Container in my Program
preferences = {
"menu": "red",
"text": "white"
}
Dictionary to store preferences
The Container Being Used
function loadPreferences() {
fetch(apiUrl)
.then(response => response.json())
.then(data => {
document.getElementById('menu').innerText = `Menu Color: ${data.menu}`;
document.getElementById('text').innerText = `Text Color: ${data.text}`;
let pColors = document.querySelectorAll('p');
pColors.forEach(p => {
p.style.color = data.text;
});
let menuItems = document.querySelectorAll('.menu-item');
menuItems.forEach(item => {
item.style.backgroundColor = data.menu;
});
})
.catch(error => {
console.error('Error fetching preferences:', error);
});
}
Preferences being pulled from the dictionary and used to replace frontend styling