Adding projects from cs50
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="Flask">
|
||||
<option name="enabled" value="true" />
|
||||
</component>
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="jquery" level="application" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
<option name="renderExternalDocumentation" value="true" />
|
||||
</component>
|
||||
<component name="TemplatesService">
|
||||
<option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
|
||||
<option name="TEMPLATE_FOLDERS">
|
||||
<list>
|
||||
<option value="$MODULE_DIR$/templates" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="TestRunnerService">
|
||||
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/final.iml" filepath="$PROJECT_DIR$/.idea/final.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="de1f1682-056b-43d2-9afd-d9f8b554aeeb" name="Default Changelist" comment="" />
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/templates/layout.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="204">
|
||||
<caret line="12" selection-start-line="12" selection-end-line="12" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/templates/riemann.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-170">
|
||||
<caret line="2" column="17" selection-start-line="2" selection-start-column="17" selection-end-line="2" selection-end-column="17" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/templates/rightSummed.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="374">
|
||||
<caret line="22" column="37" selection-start-line="22" selection-start-column="37" selection-end-line="22" selection-end-column="37" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/templates/index.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="238">
|
||||
<caret line="14" column="14" selection-start-line="14" selection-start-column="14" selection-end-line="14" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/templates/layout.html" />
|
||||
<option value="$PROJECT_DIR$/templates/index.html" />
|
||||
<option value="$PROJECT_DIR$/templates/basic.html" />
|
||||
<option value="$PROJECT_DIR$/application.py" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<option name="x" value="371" />
|
||||
<option name="y" value="-15" />
|
||||
<option name="width" value="979" />
|
||||
<option name="height" value="934" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator proportions="" version="1">
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="final" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="final" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="final" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="final" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="templates" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="node.js.detected.package.eslint" value="true" />
|
||||
<property name="node.js.path.for.package.eslint" value="project" />
|
||||
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
||||
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
|
||||
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="final" type="Python.FlaskServer">
|
||||
<module name="final" />
|
||||
<option name="target" value="$PROJECT_DIR$/application.py" />
|
||||
<option name="targetType" value="PATH" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="" />
|
||||
<option name="IS_MODULE_SDK" value="false" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||
<option name="launchJavascriptDebuger" value="false" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SvnConfiguration">
|
||||
<configuration />
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="de1f1682-056b-43d2-9afd-d9f8b554aeeb" name="Default Changelist" comment="" />
|
||||
<created>1556603970433</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1556603970433</updated>
|
||||
<workItem from="1556603972060" duration="2623000" />
|
||||
<workItem from="1556645242916" duration="3303000" />
|
||||
<workItem from="1561683875314" duration="263000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TimeTrackingManager">
|
||||
<option name="totallyTimeSpent" value="6189000" />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="-7" y="-7" width="1550" height="838" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.14879356" />
|
||||
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
|
||||
<window_info id="Favorites" order="2" side_tool="true" />
|
||||
<window_info anchor="bottom" id="Message" order="0" />
|
||||
<window_info anchor="bottom" id="Find" order="1" />
|
||||
<window_info anchor="bottom" id="Run" order="2" />
|
||||
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
|
||||
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
|
||||
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
||||
<window_info anchor="bottom" id="TODO" order="6" />
|
||||
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
|
||||
<window_info anchor="bottom" id="Version Control" order="8" />
|
||||
<window_info anchor="bottom" id="Database Changes" order="9" />
|
||||
<window_info anchor="bottom" id="Event Log" order="10" side_tool="true" />
|
||||
<window_info anchor="bottom" id="Terminal" order="11" visible="true" weight="0.4016973" />
|
||||
<window_info anchor="bottom" id="Python Console" order="12" />
|
||||
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
|
||||
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
|
||||
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
|
||||
<window_info anchor="right" id="SciView" order="3" />
|
||||
<window_info anchor="right" id="Database" order="4" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/mathquill/mathquill-0.10.1/Makefile" />
|
||||
<entry file="file://$PROJECT_DIR$/mathquill-0.10.1/Makefile" />
|
||||
<entry file="file://$PROJECT_DIR$/templates/basic.html" />
|
||||
<entry file="file://$PROJECT_DIR$/application.py" />
|
||||
<entry file="file://$PROJECT_DIR$/templates/index.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="238">
|
||||
<caret line="14" column="14" selection-start-line="14" selection-start-column="14" selection-end-line="14" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/templates/riemann.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-170">
|
||||
<caret line="2" column="17" selection-start-line="2" selection-start-column="17" selection-end-line="2" selection-end-column="17" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/templates/rightSummed.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="374">
|
||||
<caret line="22" column="37" selection-start-line="22" selection-start-column="37" selection-end-line="22" selection-end-column="37" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/templates/layout.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="204">
|
||||
<caret line="12" selection-start-line="12" selection-end-line="12" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1 @@
|
|||
"# final"
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
import os
|
||||
|
||||
from math import *
|
||||
from cs50 import SQL
|
||||
from flask import Flask, flash, jsonify, redirect, render_template, request, session
|
||||
from flask_session import Session
|
||||
from tempfile import mkdtemp
|
||||
from werkzeug.exceptions import default_exceptions, HTTPException, InternalServerError
|
||||
from werkzeug.security import check_password_hash, generate_password_hash
|
||||
import numpy as np
|
||||
import sympy as sp
|
||||
from sympy import *
|
||||
from latex2sympy import *
|
||||
from sympy.parsing.latex import parse_latex
|
||||
|
||||
|
||||
|
||||
from helpers import apology, login_required, lookup, usd
|
||||
|
||||
# Configure application
|
||||
app = Flask(__name__)
|
||||
|
||||
# Ensure templates are auto-reloaded
|
||||
app.config["TEMPLATES_AUTO_RELOAD"] = True
|
||||
|
||||
# Ensure responses aren't cached
|
||||
@app.after_request
|
||||
def after_request(response):
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
response.headers["Expires"] = 0
|
||||
response.headers["Pragma"] = "no-cache"
|
||||
return response
|
||||
|
||||
# Custom filter
|
||||
app.jinja_env.filters["usd"] = usd
|
||||
|
||||
# Configure session to use filesystem (instead of signed cookies)
|
||||
app.config["SESSION_FILE_DIR"] = mkdtemp()
|
||||
app.config["SESSION_PERMANENT"] = False
|
||||
app.config["SESSION_TYPE"] = "filesystem"
|
||||
Session(app)
|
||||
|
||||
# Configure CS50 Library to use SQLite database
|
||||
db = SQL("sqlite:///finance.db")
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
"""Intro to website"""
|
||||
return render_template("index.html")
|
||||
|
||||
@app.route("/differentiation", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def differentiation():
|
||||
if request.method == "POST":
|
||||
# Check if inputs were given
|
||||
if not request.form.get("function"):
|
||||
return apology("must provide a function", 400)
|
||||
f = request.form.get("function")
|
||||
x = symbols('x')
|
||||
f = sympify(f)
|
||||
|
||||
# Differentiate and return latex expressions
|
||||
fprime = latex(f.diff(x))
|
||||
value = latex(f)
|
||||
return render_template("differentiated.html", value=value, fprime=fprime)
|
||||
else:
|
||||
return render_template("differentiation.html")
|
||||
|
||||
@app.route("/integration", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def integration():
|
||||
if request.method == "POST":
|
||||
# Check if inputs were given
|
||||
if not request.form.get("function"):
|
||||
return apology("must provide a function", 400)
|
||||
|
||||
# Integrate and return latex expressions
|
||||
f = request.form.get("function")
|
||||
x = symbols('x')
|
||||
f = sympify(f)
|
||||
fintegral = latex(f.integrate(x))
|
||||
value = latex(f)
|
||||
return render_template("integrated.html", value=value, fintegral=fintegral)
|
||||
else:
|
||||
return render_template("integration.html")
|
||||
|
||||
@app.route("/riemann", methods = ["GET", "POST"])
|
||||
@login_required
|
||||
def riemann():
|
||||
if request.method == "POST":
|
||||
# Check if inputs were given
|
||||
if not request.form.get("function"):
|
||||
return apology("must provide a function", 400)
|
||||
if not request.form.get("lowerbound"):
|
||||
return apology("must provide a lower bound", 400)
|
||||
if not request.form.get("upperbound"):
|
||||
return apology("must provide an upper bound", 400)
|
||||
if not request.form.get("subintervals"):
|
||||
return apology("must provide a number of subintervals", 400)
|
||||
if not request.form.get("sumtype"):
|
||||
return apology("must choose left or right", 400)
|
||||
|
||||
# Get inputs, check for validity and sympify
|
||||
f = request.form.get("function")
|
||||
sumtype = request.form.get("sumtype")
|
||||
lb = int(request.form.get("lowerbound"))
|
||||
ub = int(request.form.get("upperbound"))
|
||||
si = int(request.form.get("subintervals"))
|
||||
x = symbols('x')
|
||||
f = sympify(f)
|
||||
dx = (ub - lb) / si
|
||||
value = latex(f)
|
||||
|
||||
# Run through Riemann Sum algorithm, creatings lists for display
|
||||
# of inputs, outputs, and areas (their products)
|
||||
inputs = list()
|
||||
if sumtype == "1":
|
||||
for i in range(0, si):
|
||||
inputs.append(dx * (i))
|
||||
if sumtype == "2":
|
||||
for i in range(0, si):
|
||||
inputs.append(dx * (i + 1))
|
||||
outputs = list()
|
||||
for input in inputs:
|
||||
temp = f.subs(x, input)
|
||||
outputs.append(temp)
|
||||
rectangles = list()
|
||||
for output in outputs:
|
||||
temp = output * dx
|
||||
rectangles.append(temp)
|
||||
result = sum(rectangles)
|
||||
|
||||
# Choose template based on left or right sum
|
||||
if sumtype == "1":
|
||||
return render_template("summed.html", value=value, sumtype=sumtype, lb=lb, ub=ub, si=si, dx=dx,
|
||||
inputs=inputs, outputs=outputs, rectangles=rectangles, result=result)
|
||||
else:
|
||||
return render_template("rightSummed.html", value=value, sumtype=sumtype, lb=lb, ub=ub, si=si, dx=dx,
|
||||
inputs=inputs, outputs=outputs, rectangles=rectangles, result=result)
|
||||
else:
|
||||
return render_template("riemann.html")
|
||||
|
||||
|
||||
@app.route("/maxmin", methods=["GET", "POST"])
|
||||
def maxmin():
|
||||
if request.method == "POST":
|
||||
# Check if inputs were given
|
||||
if not request.form.get("function"):
|
||||
return apology("must provide a function", 400)
|
||||
if not request.form.get("lowerbound"):
|
||||
return apology("must provide a lower bound", 400)
|
||||
if not request.form.get("upperbound"):
|
||||
return apology("must provide an upper bound", 400)
|
||||
|
||||
# Get input from form
|
||||
f = request.form.get("function")
|
||||
lb = sympify(request.form.get("lowerbound"))
|
||||
ub = sympify(request.form.get("upperbound"))
|
||||
|
||||
# Prep input for numpy / sympy
|
||||
x = symbols('x')
|
||||
f = sympify(f)
|
||||
|
||||
# Get Derivative, solve for real solutions, update candidates list
|
||||
fprime = f.diff(x)
|
||||
solutions = list()
|
||||
solutions.append(f.subs(x,0))
|
||||
candidates = list()
|
||||
for solution in solutions:
|
||||
candidates.append(solution)
|
||||
candidates.append(lb)
|
||||
candidates.append(ub)
|
||||
|
||||
# Fill values list with solutions
|
||||
values = list()
|
||||
for candidate in candidates:
|
||||
temp = f.subs(x, candidate)
|
||||
values.append(temp)
|
||||
|
||||
# Find max/min of values
|
||||
maximum = max(values)
|
||||
newvar = min(values)
|
||||
|
||||
# Turn all into latex
|
||||
value = latex(f)
|
||||
fprime = latex(fprime)
|
||||
for i, solution in enumerate(solutions):
|
||||
solutions[i] = latex(solution)
|
||||
return render_template("optimized.html", value=value, fprime=fprime, solutions=solutions, lb=lb, ub=ub,
|
||||
candidates=candidates, newvar=newvar, values=values, maximum=maximum)
|
||||
else:
|
||||
return render_template("maxmin.html")
|
||||
|
||||
@app.route("/aprox", methods=["GET", "POST"])
|
||||
def aprox():
|
||||
if request.method == "POST":
|
||||
# Check if inputs were given
|
||||
if not request.form.get("function"):
|
||||
return apology("must provide a function", 400)
|
||||
if not request.form.get("easy"):
|
||||
return apology("must provide an easy value", 400)
|
||||
if not request.form.get("hard"):
|
||||
return apology("must provide a difficult value", 400)
|
||||
|
||||
# Get inputs, sympify them, and check to see if valid
|
||||
f = request.form.get("function")
|
||||
a = request.form.get("easy")
|
||||
h = request.form.get("hard")
|
||||
x = symbols('x')
|
||||
f = sympify(f)
|
||||
a = sympify(a)
|
||||
h = sympify(h)
|
||||
if not a.is_number:
|
||||
return apology("easy value must be a number", 400)
|
||||
if not h.is_number:
|
||||
return apology("difficult value must be a number", 400)
|
||||
|
||||
# Run through Linearization algorithm
|
||||
fprime = f.diff(x)
|
||||
fa = f.subs(x, a)
|
||||
fprimea = fprime.subs(x, a)
|
||||
lh = fa + fprimea*(float(h)-float(a))
|
||||
|
||||
# Convert to latex for MathJax reading
|
||||
value = latex(f)
|
||||
fprime = latex(fprime)
|
||||
fa = latex(fa)
|
||||
lh = latex(lh)
|
||||
|
||||
return render_template("aproxd.html", value=value, fprime=fprime, a=a, h=h, fa=fa, fprimea=fprimea, lh=lh)
|
||||
else:
|
||||
return render_template("aprox.html")
|
||||
|
||||
@app.route("/check", methods=["GET"])
|
||||
def check():
|
||||
"""Return true if username available, else false, in JSON format"""
|
||||
username = request.args.get("username")
|
||||
usernames = db.execute("SELECT username FROM users WHERE username = :username", username=username)
|
||||
if username and not usernames:
|
||||
return jsonify(True)
|
||||
else:
|
||||
return jsonify(False)
|
||||
|
||||
@app.route("/login", methods=["GET", "POST"])
|
||||
def login():
|
||||
"""Log user in"""
|
||||
|
||||
# Forget any user_id
|
||||
session.clear()
|
||||
|
||||
# User reached route via POST (as by submitting a form via POST)
|
||||
if request.method == "POST":
|
||||
|
||||
# Ensure username was submitted
|
||||
if not request.form.get("username"):
|
||||
return apology("must provide username", 403)
|
||||
|
||||
# Ensure password was submitted
|
||||
elif not request.form.get("password"):
|
||||
return apology("must provide password", 403)
|
||||
|
||||
# Query database for username
|
||||
rows = db.execute("SELECT * FROM users WHERE username = :username",
|
||||
username=request.form.get("username"))
|
||||
|
||||
# Ensure username exists and password is correct
|
||||
if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
|
||||
return apology("invalid username and/or password", 403)
|
||||
|
||||
# Remember which user has logged in
|
||||
session["user_id"] = rows[0]["id"]
|
||||
|
||||
# Redirect user to home page
|
||||
return redirect("/")
|
||||
|
||||
# User reached route via GET (as by clicking a link or via redirect)
|
||||
else:
|
||||
return render_template("login.html")
|
||||
|
||||
|
||||
@app.route("/logout")
|
||||
def logout():
|
||||
"""Log user out"""
|
||||
|
||||
# Forget any user_id
|
||||
session.clear()
|
||||
|
||||
# Redirect user to login form
|
||||
return redirect("/")
|
||||
|
||||
@app.route("/register", methods=["GET", "POST"])
|
||||
def register():
|
||||
"""Register user"""
|
||||
# Forget any user_id
|
||||
session.clear()
|
||||
|
||||
# User reached route via POST (as by submitting a form via POST)
|
||||
if request.method == "POST":
|
||||
|
||||
# Ensure username was submitted
|
||||
if not request.form.get("username"):
|
||||
return apology("must provide username", 400)
|
||||
|
||||
# Ensure password was submitted
|
||||
elif not request.form.get("password"):
|
||||
return apology("must provide password", 400)
|
||||
|
||||
# Ensure passwords match
|
||||
elif not request.form.get("password") == request.form.get("confirmation"):
|
||||
return apology("passwords must match", 400)
|
||||
|
||||
# Create hash for password
|
||||
hash = generate_password_hash(request.form.get("password"))
|
||||
|
||||
# Insert username into database
|
||||
result = db.execute("Insert INTO users (username, hash) VALUES(:username, :hash)", username = request.form.get("username"), hash = hash)
|
||||
|
||||
# Check if username is already taken
|
||||
if not result:
|
||||
return apology("Username has been taken", 400)
|
||||
|
||||
# Remember which user has logged in
|
||||
session["user_id"] = result
|
||||
|
||||
# Redirect user to home page
|
||||
return redirect("/")
|
||||
|
||||
# User reached route via GET (as by clicking a link or via redirect)
|
||||
else:
|
||||
return render_template("register.html")
|
||||
|
||||
def errorhandler(e):
|
||||
"""Handle error"""
|
||||
if not isinstance(e, HTTPException):
|
||||
e = InternalServerError()
|
||||
return apology(e.name, e.code)
|
||||
|
||||
# Listen for errors
|
||||
for code in default_exceptions:
|
||||
app.errorhandler(code)(errorhandler)
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import requests
|
||||
import urllib.parse
|
||||
|
||||
from flask import redirect, render_template, request, session
|
||||
from functools import wraps
|
||||
|
||||
|
||||
def apology(message, code=400):
|
||||
"""Render message as an apology to user."""
|
||||
def escape(s):
|
||||
"""
|
||||
Escape special characters.
|
||||
|
||||
https://github.com/jacebrowning/memegen#special-characters
|
||||
"""
|
||||
for old, new in [("-", "--"), (" ", "-"), ("_", "__"), ("?", "~q"),
|
||||
("%", "~p"), ("#", "~h"), ("/", "~s"), ("\"", "''")]:
|
||||
s = s.replace(old, new)
|
||||
return s
|
||||
return render_template("apology.html", top=code, bottom=escape(message)), code
|
||||
|
||||
|
||||
def login_required(f):
|
||||
"""
|
||||
Decorate routes to require login.
|
||||
|
||||
http://flask.pocoo.org/docs/1.0/patterns/viewdecorators/
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if session.get("user_id") is None:
|
||||
return redirect("/login")
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
|
||||
def lookup(symbol):
|
||||
"""Look up quote for symbol."""
|
||||
|
||||
# Contact API
|
||||
try:
|
||||
response = requests.get(f"https://api.iextrading.com/1.0/stock/{urllib.parse.quote_plus(symbol)}/quote")
|
||||
response.raise_for_status()
|
||||
except requests.RequestException:
|
||||
return None
|
||||
|
||||
# Parse response
|
||||
try:
|
||||
quote = response.json()
|
||||
return {
|
||||
"name": quote["companyName"],
|
||||
"price": float(quote["latestPrice"]),
|
||||
"symbol": quote["symbol"]
|
||||
}
|
||||
except (KeyError, TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def usd(value):
|
||||
"""Format value as USD."""
|
||||
return f"${value:,.2f}"
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
cs50
|
||||
Flask
|
||||
Flask-Session
|
||||
requests
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* MathQuill v0.10.1 http://mathquill.com
|
||||
* by Han, Jeanine, and Mary maintainers@mathquill.com
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the
|
||||
* Mozilla Public License, v. 2.0. If a copy of the MPL
|
||||
* was not distributed with this file, You can obtain
|
||||
* one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
@font-face {
|
||||
font-family: Symbola;
|
||||
src: url(font/Symbola-basic.eot);
|
||||
src: local("Symbola Regular"), local("Symbola"), url(font/Symbola-basic.woff2) format("woff2"), url(font/Symbola-basic.woff) format("woff"), url(font/Symbola-basic.ttf) format("truetype");
|
||||
}
|
||||
.mq-editable-field {
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-editable-field .mq-cursor {
|
||||
border-left: 1px solid black;
|
||||
margin-left: -1px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 0;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-editable-field .mq-cursor.mq-blink {
|
||||
visibility: hidden;
|
||||
}
|
||||
.mq-editable-field,
|
||||
.mq-math-mode .mq-editable-field {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
.mq-editable-field.mq-focused,
|
||||
.mq-math-mode .mq-editable-field.mq-focused {
|
||||
-webkit-box-shadow: #8bd 0 0 1px 2px, inset #6ae 0 0 2px 0;
|
||||
-moz-box-shadow: #8bd 0 0 1px 2px, inset #6ae 0 0 2px 0;
|
||||
box-shadow: #8bd 0 0 1px 2px, inset #6ae 0 0 2px 0;
|
||||
border-color: #709AC0;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-editable-field {
|
||||
margin: 1px;
|
||||
}
|
||||
.mq-editable-field .mq-latex-command-input {
|
||||
color: inherit;
|
||||
font-family: "Courier New", monospace;
|
||||
border: 1px solid gray;
|
||||
padding-right: 1px;
|
||||
margin-right: 1px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
.mq-editable-field .mq-latex-command-input.mq-empty {
|
||||
background: transparent;
|
||||
}
|
||||
.mq-editable-field .mq-latex-command-input.mq-hasCursor {
|
||||
border-color: ActiveBorder;
|
||||
}
|
||||
.mq-editable-field.mq-empty:after,
|
||||
.mq-editable-field.mq-text-mode:after,
|
||||
.mq-math-mode .mq-empty:after {
|
||||
visibility: hidden;
|
||||
content: 'c';
|
||||
}
|
||||
.mq-editable-field .mq-cursor:only-child:after,
|
||||
.mq-editable-field .mq-textarea + .mq-cursor:last-child:after {
|
||||
visibility: hidden;
|
||||
content: 'c';
|
||||
}
|
||||
.mq-editable-field .mq-text-mode .mq-cursor:only-child:after {
|
||||
content: '';
|
||||
}
|
||||
.mq-editable-field.mq-text-mode {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.mq-root-block,
|
||||
.mq-math-mode .mq-root-block {
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.mq-math-mode {
|
||||
font-variant: normal;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 115%;
|
||||
line-height: 1;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode .mq-non-leaf,
|
||||
.mq-math-mode .mq-scaled {
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode var,
|
||||
.mq-math-mode .mq-text-mode,
|
||||
.mq-math-mode .mq-nonSymbola {
|
||||
font-family: "Times New Roman", Symbola, serif;
|
||||
line-height: .9;
|
||||
}
|
||||
.mq-math-mode * {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-color: black;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.mq-math-mode .mq-empty {
|
||||
background: #ccc;
|
||||
}
|
||||
.mq-math-mode .mq-empty.mq-root-block {
|
||||
background: transparent;
|
||||
}
|
||||
.mq-math-mode.mq-empty {
|
||||
background: transparent;
|
||||
}
|
||||
.mq-math-mode .mq-text-mode {
|
||||
font-size: 87%;
|
||||
}
|
||||
.mq-math-mode .mq-font {
|
||||
font: 1em "Times New Roman", Symbola, serif;
|
||||
}
|
||||
.mq-math-mode .mq-font * {
|
||||
font-family: inherit;
|
||||
font-style: inherit;
|
||||
}
|
||||
.mq-math-mode b,
|
||||
.mq-math-mode b.mq-font {
|
||||
font-weight: bolder;
|
||||
}
|
||||
.mq-math-mode var,
|
||||
.mq-math-mode i,
|
||||
.mq-math-mode i.mq-font {
|
||||
font-style: italic;
|
||||
}
|
||||
.mq-math-mode var.mq-f {
|
||||
margin-right: 0.2em;
|
||||
margin-left: 0.1em;
|
||||
}
|
||||
.mq-math-mode .mq-roman var.mq-f {
|
||||
margin: 0;
|
||||
}
|
||||
.mq-math-mode big {
|
||||
font-size: 125%;
|
||||
}
|
||||
.mq-math-mode .mq-roman {
|
||||
font-style: normal;
|
||||
}
|
||||
.mq-math-mode .mq-sans-serif {
|
||||
font-family: sans-serif, Symbola, serif;
|
||||
}
|
||||
.mq-math-mode .mq-monospace {
|
||||
font-family: monospace, Symbola, serif;
|
||||
}
|
||||
.mq-math-mode .mq-overline {
|
||||
border-top: 1px solid black;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-underline {
|
||||
border-bottom: 1px solid black;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-binary-operator {
|
||||
padding: 0 0.2em;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode .mq-supsub {
|
||||
font-size: 90%;
|
||||
vertical-align: -0.5em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub.mq-limit {
|
||||
font-size: 80%;
|
||||
vertical-align: -0.4em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub.mq-sup-only {
|
||||
vertical-align: .5em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub.mq-sup-only .mq-sup {
|
||||
display: inline-block;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
.mq-math-mode .mq-supsub .mq-sup {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-supsub .mq-sub {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
.mq-math-mode .mq-supsub.mq-limit .mq-sub {
|
||||
margin-left: -0.25em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub .mq-binary-operator {
|
||||
padding: 0 .1em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub .mq-fraction {
|
||||
font-size: 70%;
|
||||
}
|
||||
.mq-math-mode sup.mq-nthroot {
|
||||
font-size: 80%;
|
||||
vertical-align: 0.8em;
|
||||
margin-right: -0.6em;
|
||||
margin-left: .2em;
|
||||
min-width: .5em;
|
||||
}
|
||||
.mq-math-mode .mq-paren {
|
||||
padding: 0 .1em;
|
||||
vertical-align: top;
|
||||
-webkit-transform-origin: center .06em;
|
||||
-moz-transform-origin: center .06em;
|
||||
-ms-transform-origin: center .06em;
|
||||
-o-transform-origin: center .06em;
|
||||
transform-origin: center .06em;
|
||||
}
|
||||
.mq-math-mode .mq-paren.mq-ghost {
|
||||
color: silver;
|
||||
}
|
||||
.mq-math-mode .mq-paren + span {
|
||||
margin-top: .1em;
|
||||
margin-bottom: .1em;
|
||||
}
|
||||
.mq-math-mode .mq-array {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
.mq-math-mode .mq-array > span {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-operator-name {
|
||||
font-family: Symbola, "Times New Roman", serif;
|
||||
line-height: .9;
|
||||
font-style: normal;
|
||||
}
|
||||
.mq-math-mode var.mq-operator-name.mq-first {
|
||||
padding-left: .2em;
|
||||
}
|
||||
.mq-math-mode var.mq-operator-name.mq-last {
|
||||
padding-right: .2em;
|
||||
}
|
||||
.mq-math-mode .mq-fraction {
|
||||
font-size: 90%;
|
||||
text-align: center;
|
||||
vertical-align: -0.4em;
|
||||
padding: 0 .2em;
|
||||
}
|
||||
.mq-math-mode .mq-fraction,
|
||||
.mq-math-mode .mq-large-operator,
|
||||
.mq-math-mode x:-moz-any-link {
|
||||
display: -moz-groupbox;
|
||||
}
|
||||
.mq-math-mode .mq-fraction,
|
||||
.mq-math-mode .mq-large-operator,
|
||||
.mq-math-mode x:-moz-any-link,
|
||||
.mq-math-mode x:default {
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode .mq-numerator,
|
||||
.mq-math-mode .mq-denominator {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-numerator {
|
||||
padding: 0 0.1em;
|
||||
}
|
||||
.mq-math-mode .mq-denominator {
|
||||
border-top: 1px solid;
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0.1em;
|
||||
}
|
||||
.mq-math-mode .mq-sqrt-prefix {
|
||||
padding-top: 0;
|
||||
position: relative;
|
||||
top: 0.1em;
|
||||
vertical-align: top;
|
||||
-webkit-transform-origin: top;
|
||||
-moz-transform-origin: top;
|
||||
-ms-transform-origin: top;
|
||||
-o-transform-origin: top;
|
||||
transform-origin: top;
|
||||
}
|
||||
.mq-math-mode .mq-sqrt-stem {
|
||||
border-top: 1px solid;
|
||||
margin-top: 1px;
|
||||
padding-left: .15em;
|
||||
padding-right: .2em;
|
||||
margin-right: .1em;
|
||||
padding-top: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-vector-prefix {
|
||||
display: block;
|
||||
text-align: center;
|
||||
line-height: .25em;
|
||||
margin-bottom: -0.1em;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
.mq-math-mode .mq-vector-stem {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-large-operator {
|
||||
text-align: center;
|
||||
}
|
||||
.mq-math-mode .mq-large-operator .mq-from,
|
||||
.mq-math-mode .mq-large-operator big,
|
||||
.mq-math-mode .mq-large-operator .mq-to {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-large-operator .mq-from,
|
||||
.mq-math-mode .mq-large-operator .mq-to {
|
||||
font-size: 80%;
|
||||
}
|
||||
.mq-math-mode .mq-large-operator .mq-from {
|
||||
float: right;
|
||||
/* take out of normal flow to manipulate baseline */
|
||||
width: 100%;
|
||||
}
|
||||
.mq-math-mode,
|
||||
.mq-math-mode .mq-editable-field {
|
||||
cursor: text;
|
||||
font-family: Symbola, "Times New Roman", serif;
|
||||
}
|
||||
.mq-math-mode .mq-overarrow {
|
||||
border-top: 1px solid black;
|
||||
margin-top: 1px;
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
.mq-math-mode .mq-overarrow:before {
|
||||
display: block;
|
||||
position: relative;
|
||||
top: -0.34em;
|
||||
font-size: 0.5em;
|
||||
line-height: 0em;
|
||||
content: '\27A4';
|
||||
text-align: right;
|
||||
}
|
||||
.mq-math-mode .mq-overarrow.mq-arrow-left:before {
|
||||
-moz-transform: scaleX(-1);
|
||||
-o-transform: scaleX(-1);
|
||||
-webkit-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
filter: FlipH;
|
||||
-ms-filter: "FlipH";
|
||||
}
|
||||
.mq-math-mode .mq-selection,
|
||||
.mq-editable-field .mq-selection,
|
||||
.mq-math-mode .mq-selection .mq-non-leaf,
|
||||
.mq-editable-field .mq-selection .mq-non-leaf,
|
||||
.mq-math-mode .mq-selection .mq-scaled,
|
||||
.mq-editable-field .mq-selection .mq-scaled {
|
||||
background: #B4D5FE !important;
|
||||
background: Highlight !important;
|
||||
color: HighlightText;
|
||||
border-color: HighlightText;
|
||||
}
|
||||
.mq-math-mode .mq-selection .mq-matrixed,
|
||||
.mq-editable-field .mq-selection .mq-matrixed {
|
||||
background: #39F !important;
|
||||
}
|
||||
.mq-math-mode .mq-selection .mq-matrixed-container,
|
||||
.mq-editable-field .mq-selection .mq-matrixed-container {
|
||||
filter: progid:DXImageTransform.Microsoft.Chroma(color='#3399FF') !important;
|
||||
}
|
||||
.mq-math-mode .mq-selection.mq-blur,
|
||||
.mq-editable-field .mq-selection.mq-blur,
|
||||
.mq-math-mode .mq-selection.mq-blur .mq-non-leaf,
|
||||
.mq-editable-field .mq-selection.mq-blur .mq-non-leaf,
|
||||
.mq-math-mode .mq-selection.mq-blur .mq-scaled,
|
||||
.mq-editable-field .mq-selection.mq-blur .mq-scaled,
|
||||
.mq-math-mode .mq-selection.mq-blur .mq-matrixed,
|
||||
.mq-editable-field .mq-selection.mq-blur .mq-matrixed {
|
||||
background: #D4D4D4 !important;
|
||||
color: black;
|
||||
border-color: black;
|
||||
}
|
||||
.mq-math-mode .mq-selection.mq-blur .mq-matrixed-container,
|
||||
.mq-editable-field .mq-selection.mq-blur .mq-matrixed-container {
|
||||
filter: progid:DXImageTransform.Microsoft.Chroma(color='#D4D4D4') !important;
|
||||
}
|
||||
.mq-editable-field .mq-textarea,
|
||||
.mq-math-mode .mq-textarea {
|
||||
position: relative;
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
.mq-editable-field .mq-textarea *,
|
||||
.mq-math-mode .mq-textarea *,
|
||||
.mq-editable-field .mq-selectable,
|
||||
.mq-math-mode .mq-selectable {
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
user-select: text;
|
||||
position: absolute;
|
||||
clip: rect(1em 1em 1em 1em);
|
||||
-webkit-transform: scale(0);
|
||||
-moz-transform: scale(0);
|
||||
-ms-transform: scale(0);
|
||||
-o-transform: scale(0);
|
||||
transform: scale(0);
|
||||
resize: none;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-matrixed {
|
||||
background: white;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode .mq-matrixed-container {
|
||||
filter: progid:DXImageTransform.Microsoft.Chroma(color='white');
|
||||
margin-top: -0.1em;
|
||||
}
|
||||
|
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* MathQuill v0.10.1 http://mathquill.com
|
||||
* by Han, Jeanine, and Mary maintainers@mathquill.com
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the
|
||||
* Mozilla Public License, v. 2.0. If a copy of the MPL
|
||||
* was not distributed with this file, You can obtain
|
||||
* one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
@font-face {
|
||||
font-family: Symbola;
|
||||
src: url(font/Symbola.eot);
|
||||
src: local("Symbola Regular"), local("Symbola"), url(font/Symbola.woff2) format("woff2"), url(font/Symbola.woff) format("woff"), url(font/Symbola.ttf) format("truetype"), url(font/Symbola.otf) format("opentype"), url(font/Symbola.svg#Symbola) format("svg");
|
||||
}
|
||||
.mq-editable-field {
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-editable-field .mq-cursor {
|
||||
border-left: 1px solid black;
|
||||
margin-left: -1px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 0;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-editable-field .mq-cursor.mq-blink {
|
||||
visibility: hidden;
|
||||
}
|
||||
.mq-editable-field,
|
||||
.mq-math-mode .mq-editable-field {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
.mq-editable-field.mq-focused,
|
||||
.mq-math-mode .mq-editable-field.mq-focused {
|
||||
-webkit-box-shadow: #8bd 0 0 1px 2px, inset #6ae 0 0 2px 0;
|
||||
-moz-box-shadow: #8bd 0 0 1px 2px, inset #6ae 0 0 2px 0;
|
||||
box-shadow: #8bd 0 0 1px 2px, inset #6ae 0 0 2px 0;
|
||||
border-color: #709AC0;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-editable-field {
|
||||
margin: 1px;
|
||||
}
|
||||
.mq-editable-field .mq-latex-command-input {
|
||||
color: inherit;
|
||||
font-family: "Courier New", monospace;
|
||||
border: 1px solid gray;
|
||||
padding-right: 1px;
|
||||
margin-right: 1px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
.mq-editable-field .mq-latex-command-input.mq-empty {
|
||||
background: transparent;
|
||||
}
|
||||
.mq-editable-field .mq-latex-command-input.mq-hasCursor {
|
||||
border-color: ActiveBorder;
|
||||
}
|
||||
.mq-editable-field.mq-empty:after,
|
||||
.mq-editable-field.mq-text-mode:after,
|
||||
.mq-math-mode .mq-empty:after {
|
||||
visibility: hidden;
|
||||
content: 'c';
|
||||
}
|
||||
.mq-editable-field .mq-cursor:only-child:after,
|
||||
.mq-editable-field .mq-textarea + .mq-cursor:last-child:after {
|
||||
visibility: hidden;
|
||||
content: 'c';
|
||||
}
|
||||
.mq-editable-field .mq-text-mode .mq-cursor:only-child:after {
|
||||
content: '';
|
||||
}
|
||||
.mq-editable-field.mq-text-mode {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.mq-root-block,
|
||||
.mq-math-mode .mq-root-block {
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.mq-math-mode {
|
||||
font-variant: normal;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 115%;
|
||||
line-height: 1;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode .mq-non-leaf,
|
||||
.mq-math-mode .mq-scaled {
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode var,
|
||||
.mq-math-mode .mq-text-mode,
|
||||
.mq-math-mode .mq-nonSymbola {
|
||||
font-family: "Times New Roman", Symbola, serif;
|
||||
line-height: .9;
|
||||
}
|
||||
.mq-math-mode * {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-color: black;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.mq-math-mode .mq-empty {
|
||||
background: #ccc;
|
||||
}
|
||||
.mq-math-mode .mq-empty.mq-root-block {
|
||||
background: transparent;
|
||||
}
|
||||
.mq-math-mode.mq-empty {
|
||||
background: transparent;
|
||||
}
|
||||
.mq-math-mode .mq-text-mode {
|
||||
font-size: 87%;
|
||||
}
|
||||
.mq-math-mode .mq-font {
|
||||
font: 1em "Times New Roman", Symbola, serif;
|
||||
}
|
||||
.mq-math-mode .mq-font * {
|
||||
font-family: inherit;
|
||||
font-style: inherit;
|
||||
}
|
||||
.mq-math-mode b,
|
||||
.mq-math-mode b.mq-font {
|
||||
font-weight: bolder;
|
||||
}
|
||||
.mq-math-mode var,
|
||||
.mq-math-mode i,
|
||||
.mq-math-mode i.mq-font {
|
||||
font-style: italic;
|
||||
}
|
||||
.mq-math-mode var.mq-f {
|
||||
margin-right: 0.2em;
|
||||
margin-left: 0.1em;
|
||||
}
|
||||
.mq-math-mode .mq-roman var.mq-f {
|
||||
margin: 0;
|
||||
}
|
||||
.mq-math-mode big {
|
||||
font-size: 125%;
|
||||
}
|
||||
.mq-math-mode .mq-roman {
|
||||
font-style: normal;
|
||||
}
|
||||
.mq-math-mode .mq-sans-serif {
|
||||
font-family: sans-serif, Symbola, serif;
|
||||
}
|
||||
.mq-math-mode .mq-monospace {
|
||||
font-family: monospace, Symbola, serif;
|
||||
}
|
||||
.mq-math-mode .mq-overline {
|
||||
border-top: 1px solid black;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-underline {
|
||||
border-bottom: 1px solid black;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-binary-operator {
|
||||
padding: 0 0.2em;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode .mq-supsub {
|
||||
font-size: 90%;
|
||||
vertical-align: -0.5em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub.mq-limit {
|
||||
font-size: 80%;
|
||||
vertical-align: -0.4em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub.mq-sup-only {
|
||||
vertical-align: .5em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub.mq-sup-only .mq-sup {
|
||||
display: inline-block;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
.mq-math-mode .mq-supsub .mq-sup {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-supsub .mq-sub {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
.mq-math-mode .mq-supsub.mq-limit .mq-sub {
|
||||
margin-left: -0.25em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub .mq-binary-operator {
|
||||
padding: 0 .1em;
|
||||
}
|
||||
.mq-math-mode .mq-supsub .mq-fraction {
|
||||
font-size: 70%;
|
||||
}
|
||||
.mq-math-mode sup.mq-nthroot {
|
||||
font-size: 80%;
|
||||
vertical-align: 0.8em;
|
||||
margin-right: -0.6em;
|
||||
margin-left: .2em;
|
||||
min-width: .5em;
|
||||
}
|
||||
.mq-math-mode .mq-paren {
|
||||
padding: 0 .1em;
|
||||
vertical-align: top;
|
||||
-webkit-transform-origin: center .06em;
|
||||
-moz-transform-origin: center .06em;
|
||||
-ms-transform-origin: center .06em;
|
||||
-o-transform-origin: center .06em;
|
||||
transform-origin: center .06em;
|
||||
}
|
||||
.mq-math-mode .mq-paren.mq-ghost {
|
||||
color: silver;
|
||||
}
|
||||
.mq-math-mode .mq-paren + span {
|
||||
margin-top: .1em;
|
||||
margin-bottom: .1em;
|
||||
}
|
||||
.mq-math-mode .mq-array {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
.mq-math-mode .mq-array > span {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-operator-name {
|
||||
font-family: Symbola, "Times New Roman", serif;
|
||||
line-height: .9;
|
||||
font-style: normal;
|
||||
}
|
||||
.mq-math-mode var.mq-operator-name.mq-first {
|
||||
padding-left: .2em;
|
||||
}
|
||||
.mq-math-mode var.mq-operator-name.mq-last {
|
||||
padding-right: .2em;
|
||||
}
|
||||
.mq-math-mode .mq-fraction {
|
||||
font-size: 90%;
|
||||
text-align: center;
|
||||
vertical-align: -0.4em;
|
||||
padding: 0 .2em;
|
||||
}
|
||||
.mq-math-mode .mq-fraction,
|
||||
.mq-math-mode .mq-large-operator,
|
||||
.mq-math-mode x:-moz-any-link {
|
||||
display: -moz-groupbox;
|
||||
}
|
||||
.mq-math-mode .mq-fraction,
|
||||
.mq-math-mode .mq-large-operator,
|
||||
.mq-math-mode x:-moz-any-link,
|
||||
.mq-math-mode x:default {
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode .mq-numerator,
|
||||
.mq-math-mode .mq-denominator {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-numerator {
|
||||
padding: 0 0.1em;
|
||||
}
|
||||
.mq-math-mode .mq-denominator {
|
||||
border-top: 1px solid;
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0.1em;
|
||||
}
|
||||
.mq-math-mode .mq-sqrt-prefix {
|
||||
padding-top: 0;
|
||||
position: relative;
|
||||
top: 0.1em;
|
||||
vertical-align: top;
|
||||
-webkit-transform-origin: top;
|
||||
-moz-transform-origin: top;
|
||||
-ms-transform-origin: top;
|
||||
-o-transform-origin: top;
|
||||
transform-origin: top;
|
||||
}
|
||||
.mq-math-mode .mq-sqrt-stem {
|
||||
border-top: 1px solid;
|
||||
margin-top: 1px;
|
||||
padding-left: .15em;
|
||||
padding-right: .2em;
|
||||
margin-right: .1em;
|
||||
padding-top: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-vector-prefix {
|
||||
display: block;
|
||||
text-align: center;
|
||||
line-height: .25em;
|
||||
margin-bottom: -0.1em;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
.mq-math-mode .mq-vector-stem {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-large-operator {
|
||||
text-align: center;
|
||||
}
|
||||
.mq-math-mode .mq-large-operator .mq-from,
|
||||
.mq-math-mode .mq-large-operator big,
|
||||
.mq-math-mode .mq-large-operator .mq-to {
|
||||
display: block;
|
||||
}
|
||||
.mq-math-mode .mq-large-operator .mq-from,
|
||||
.mq-math-mode .mq-large-operator .mq-to {
|
||||
font-size: 80%;
|
||||
}
|
||||
.mq-math-mode .mq-large-operator .mq-from {
|
||||
float: right;
|
||||
/* take out of normal flow to manipulate baseline */
|
||||
width: 100%;
|
||||
}
|
||||
.mq-math-mode,
|
||||
.mq-math-mode .mq-editable-field {
|
||||
cursor: text;
|
||||
font-family: Symbola, "Times New Roman", serif;
|
||||
}
|
||||
.mq-math-mode .mq-overarrow {
|
||||
border-top: 1px solid black;
|
||||
margin-top: 1px;
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
.mq-math-mode .mq-overarrow:before {
|
||||
display: block;
|
||||
position: relative;
|
||||
top: -0.34em;
|
||||
font-size: 0.5em;
|
||||
line-height: 0em;
|
||||
content: '\27A4';
|
||||
text-align: right;
|
||||
}
|
||||
.mq-math-mode .mq-overarrow.mq-arrow-left:before {
|
||||
-moz-transform: scaleX(-1);
|
||||
-o-transform: scaleX(-1);
|
||||
-webkit-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
filter: FlipH;
|
||||
-ms-filter: "FlipH";
|
||||
}
|
||||
.mq-math-mode .mq-selection,
|
||||
.mq-editable-field .mq-selection,
|
||||
.mq-math-mode .mq-selection .mq-non-leaf,
|
||||
.mq-editable-field .mq-selection .mq-non-leaf,
|
||||
.mq-math-mode .mq-selection .mq-scaled,
|
||||
.mq-editable-field .mq-selection .mq-scaled {
|
||||
background: #B4D5FE !important;
|
||||
background: Highlight !important;
|
||||
color: HighlightText;
|
||||
border-color: HighlightText;
|
||||
}
|
||||
.mq-math-mode .mq-selection .mq-matrixed,
|
||||
.mq-editable-field .mq-selection .mq-matrixed {
|
||||
background: #39F !important;
|
||||
}
|
||||
.mq-math-mode .mq-selection .mq-matrixed-container,
|
||||
.mq-editable-field .mq-selection .mq-matrixed-container {
|
||||
filter: progid:DXImageTransform.Microsoft.Chroma(color='#3399FF') !important;
|
||||
}
|
||||
.mq-math-mode .mq-selection.mq-blur,
|
||||
.mq-editable-field .mq-selection.mq-blur,
|
||||
.mq-math-mode .mq-selection.mq-blur .mq-non-leaf,
|
||||
.mq-editable-field .mq-selection.mq-blur .mq-non-leaf,
|
||||
.mq-math-mode .mq-selection.mq-blur .mq-scaled,
|
||||
.mq-editable-field .mq-selection.mq-blur .mq-scaled,
|
||||
.mq-math-mode .mq-selection.mq-blur .mq-matrixed,
|
||||
.mq-editable-field .mq-selection.mq-blur .mq-matrixed {
|
||||
background: #D4D4D4 !important;
|
||||
color: black;
|
||||
border-color: black;
|
||||
}
|
||||
.mq-math-mode .mq-selection.mq-blur .mq-matrixed-container,
|
||||
.mq-editable-field .mq-selection.mq-blur .mq-matrixed-container {
|
||||
filter: progid:DXImageTransform.Microsoft.Chroma(color='#D4D4D4') !important;
|
||||
}
|
||||
.mq-editable-field .mq-textarea,
|
||||
.mq-math-mode .mq-textarea {
|
||||
position: relative;
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
.mq-editable-field .mq-textarea *,
|
||||
.mq-math-mode .mq-textarea *,
|
||||
.mq-editable-field .mq-selectable,
|
||||
.mq-math-mode .mq-selectable {
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
user-select: text;
|
||||
position: absolute;
|
||||
clip: rect(1em 1em 1em 1em);
|
||||
-webkit-transform: scale(0);
|
||||
-moz-transform: scale(0);
|
||||
-ms-transform: scale(0);
|
||||
-o-transform: scale(0);
|
||||
transform: scale(0);
|
||||
resize: none;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.mq-math-mode .mq-matrixed {
|
||||
background: white;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.mq-math-mode .mq-matrixed-container {
|
||||
filter: progid:DXImageTransform.Microsoft.Chroma(color='white');
|
||||
margin-top: -0.1em;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
nav .navbar-brand
|
||||
{
|
||||
/* size for brand */
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
/* colors for brand */
|
||||
nav .navbar-brand .blue
|
||||
{
|
||||
color: #537fbe;
|
||||
}
|
||||
nav .navbar-brand .red
|
||||
{
|
||||
color: #ea433b;
|
||||
}
|
||||
nav .navbar-brand .yellow
|
||||
{
|
||||
color: #f5b82e;
|
||||
}
|
||||
nav .navbar-brand .green
|
||||
{
|
||||
color: #2e944b;
|
||||
}
|
||||
|
||||
main .form-control
|
||||
{
|
||||
/* center form controls */
|
||||
display: inline-block;
|
||||
|
||||
/* override Bootstrap's 100% width for form controls */
|
||||
width: auto;
|
||||
}
|
||||
|
||||
main
|
||||
{
|
||||
/* scroll horizontally as needed */
|
||||
overflow-x: auto;
|
||||
|
||||
/* center contents */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
main img
|
||||
{
|
||||
/* constrain images on small screens */
|
||||
max-width: 100%;
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Differentiation
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<p>Function you would like to Derive: </p>
|
||||
<p>Type math here: <span id="math-field"></span></p>
|
||||
<form action="/differentiation" method="post">
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="function" placeholder="Function" type="hidden" id="function" />
|
||||
</div>
|
||||
<p id="jp">Your Input Will Appear Here</p>
|
||||
<button class="btn btn-primary" type="submit" id="btn">Derive</button>
|
||||
</form>
|
||||
<script>
|
||||
let value = $("#function").val();
|
||||
$(document).ready(function(){
|
||||
$('#function').on('input', function() {
|
||||
let testvalue = $('#function').val();
|
||||
$('#jp').html("$f(x) = "+testvalue+"$");
|
||||
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var mathFieldSpan = document.getElementById('math-field');
|
||||
var latexSpan = document.getElementById('latex');
|
||||
|
||||
var MQ = MathQuill.getInterface(2); // for backcompat
|
||||
var mathField = MQ.MathField(mathFieldSpan, {
|
||||
spaceBehavesLikeTab: true, // configurable
|
||||
handlers: {
|
||||
edit: function() { // useful event handlers
|
||||
latexSpan.textContent = mathField.latex(); // simple API
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var formInput = document.getElementById("function")
|
||||
$(document).ready(function(){
|
||||
$('#btn').click(function (evt) {
|
||||
document.getElementById("function").value = mathField.latex();
|
||||
})
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Apology
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<img alt="{{ top }}" class="border" src="http://memegen.link/custom/{{ top | urlencode }}/{{ bottom | urlencode }}.jpg?alt=https://i.imgur.com/CsCgN7Ll.png" title="{{ top }}">
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Approximation
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<span>Function you would like to Approximate:</span>
|
||||
<form action="/aprox" method="post">
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="function" placeholder="Function" type="text" id="function">
|
||||
</div>
|
||||
<p id="jp">Your Input Will Appear Here</p>
|
||||
<p>To create the Linearization of f at a, L(x) = f(a) + f'(a)(x-a), we need an easy to calculate value, a,
|
||||
and a difficult to find value for x</p>
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="easy" placeholder="Easy Value a" type="text" id="easy">
|
||||
<input autocomplete="off" autofocus class="form-control" name="hard" placeholder="Difficult Value for x" type="text" id="hard">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Approximate</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
let value = $("#function").val();
|
||||
$(document).ready(function(){
|
||||
$('#function').on('input', function() {
|
||||
let testvalue = $('#function').val();
|
||||
$('#jp').html("$f(x) = "+testvalue+"$");
|
||||
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Differentiated
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div>
|
||||
<p>Your function is $f(x) = {{ value }}$</p>
|
||||
<p>Your Linear Approximation of $f(x)$ at $x = {{ h }}$ is ${{ lh }}$</p>
|
||||
</div>
|
||||
<table class="table" action="optimized">
|
||||
<tbody>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 1</td>
|
||||
<td>Setup L(x)</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$L(x) = f({{ a }}) + f'({{ a }})(x-{{ a }})$</td>
|
||||
</tr>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 2</td>
|
||||
<td>Take the Derivative</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f'(x) = {{ fprime }}$</td>
|
||||
</tr>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 3</td>
|
||||
<td>Plug in values</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f({{ a }}) = {{ fa }}$</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f'({{ a }}) = {{ fprimea }}$</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$L(x) = {{ fa }} + [{{ fprimea }}(x - {{ a }})]$</td>
|
||||
</tr>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 4</td>
|
||||
<td>Use our $L(x)$ to approximate $f({{ h }})$</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$L({{ h }}) = {{ fa }} + [{{ fprimea }}({{ h }} - {{ a }})]$</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td> $= {{ lh }}$</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Differentiated
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div>
|
||||
<p>For $f(x) = {{ value }}$</p>
|
||||
<p>$f'(x) = {{ fprime }}$</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Differentiation
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<p>Function you would like to Derive: </p>
|
||||
<form action="/differentiation" method="post">
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="function" placeholder="Function" type="text" id="function">
|
||||
</div>
|
||||
<p id="jp">Your Input Will Appear Here</p>
|
||||
<button class="btn btn-primary" type="submit">Differentiate</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
let value = $("#function").val();
|
||||
$(document).ready(function(){
|
||||
$('#function').on('input', function() {
|
||||
let testvalue = $('#function').val();
|
||||
$('#jp').html("$f(x) = "+testvalue+"$");
|
||||
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Index
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<p>This is a website dedicated to making the lives of calculus students easier, if ever so slightly.</p>
|
||||
<P>All function inputs will be taken assuming 'x' as your variable. All other letters will be treated as constants</P>
|
||||
<p>That noted, you may enter terms for well known constants and they will likely be accounted for</p>
|
||||
<p>As an example you could enter the function $sin(\pi x)$ with the notation sin(pi*x)</p>
|
||||
<p>As a once struggling calculus student, I highly recommend this site be used either to check your work or as a tool
|
||||
to understand the steps behind those problems which you failed in solving alone</p>
|
||||
<p>Good luck!</p>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Integrated
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div>
|
||||
<p>Your Equation is: ${{ value }}$</p>
|
||||
<p>Your integral is: ${{ fintegral }}$</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Integration
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<p>Function you would like to Integrate: </p>
|
||||
<form action="/integration" method="post">
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="function" placeholder="Function" type="text" id="function">
|
||||
</div>
|
||||
<p id="jp">Your Input Will Appear Here</p>
|
||||
<button class="btn btn-primary" type="submit">Integrate</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
let value = $("#function").val();
|
||||
$(document).ready(function(){
|
||||
$('#function').on('input', function() {
|
||||
let testvalue = $('#function').val();
|
||||
$('#jp').html("$f(x) = "+testvalue+"$");
|
||||
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- documentation at http://getbootstrap.com/docs/4.1/, alternative themes at https://bootswatch.com/ -->
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- https://favicon.io/emoji-favicons/money-mouth-face/ -->
|
||||
<link href="/static/favicon.ico" rel="icon">
|
||||
|
||||
<link href="/static/styles.css" rel="stylesheet">
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
|
||||
|
||||
<!-- MathJax Integration and configuration -->
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML' async></script>
|
||||
<script type="text/x-mathjax-config">
|
||||
MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
|
||||
</script>
|
||||
|
||||
<!-- MathQuill Link -->
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/mathquill/0.10.1/mathquill.min.css">`
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathquill/0.10.1/mathquill.min.js" type="text/javascript"></script>
|
||||
<script>var MQ = MathQuill.getInterface(2);</script>
|
||||
|
||||
<title>C$50 Math: {% block title %}{% endblock %}</title>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light border">
|
||||
<a class="navbar-brand" href="/"><span class="blue">C</span><span class="red">$</span><span class="yellow">5</span><span class="green">0</span> <span class="red">Math</span></a>
|
||||
<button aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#navbar" data-toggle="collapse" type="button">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbar">
|
||||
{% if session.user_id %}
|
||||
<ul class="navbar-nav mr-auto mt-2">
|
||||
<li class="nav-item"><a class="nav-link" href="/differentiation">Differentiation</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/integration">Integration</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/maxmin">Max/Min</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/aprox">Linearization</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/riemann">Riemann</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto mt-2">
|
||||
<li class="nav-item"><a class="nav-link" href="/logout">Log Out</a></li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<ul class="navbar-nav ml-auto mt-2">
|
||||
<li class="nav-item"><a class="nav-link" href="/register">Register</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/login">Log In</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{% if get_flashed_messages() %}
|
||||
<header>
|
||||
<div class="alert alert-primary border text-center" role="alert">
|
||||
{{ get_flashed_messages() | join(" ") }}
|
||||
</div>
|
||||
</header>
|
||||
{% endif %}
|
||||
|
||||
<main class="container p-5">
|
||||
{% block main %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer class="small text-center text-muted">
|
||||
Huge thanks to the staff at Harvard's <a href="https://cs50.harvard.edu/college/">CS50</a>.
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Log In
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form action="/login" method="post">
|
||||
<div class="form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="username" placeholder="Username" type="text">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input class="form-control" name="password" placeholder="Password" type="password">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Log In</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Max/Min
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<span>Function you would like to Max/Min:</span>
|
||||
<form action="/maxmin" method="post">
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="function" placeholder="Function" type="text" id="function">
|
||||
</div>
|
||||
<p id="jp">Your Input Will Appear Here</p>
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="lowerbound" placeholder="Lowerbound" type="text" id="lowerbound">
|
||||
<input autocomplete="off" autofocus class="form-control" name="upperbound" placeholder="Upperbound" type="text" id="upperbound">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Optimize</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
let value = $("#function").val();
|
||||
$(document).ready(function(){
|
||||
$('#function').on('input', function() {
|
||||
let testvalue = $('#function').val();
|
||||
$('#jp').html("$f(x) = "+testvalue+"$");
|
||||
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Optimized
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div>
|
||||
<p>Your function is $f(x) = {{ value }}$</p>
|
||||
<p>Your maximum value is ${{ maximum }}$ and your minimum value is ${{ newvar }}$</p>
|
||||
</div>
|
||||
<table class="table table-hover" action="optimized">
|
||||
<tbody>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 1</td>
|
||||
<td>Take the Derivative</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f'(x) = {{ fprime }}$</td>
|
||||
</tr>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 2</td>
|
||||
<td>Set $f'(x) = 0$</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$0 = {{ fprime }}$</td>
|
||||
</tr>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 3</td>
|
||||
<td>Solve for $x$:</td>
|
||||
</tr>
|
||||
{% for solution in solutions %}
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$x = {{ solution }}$</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 4</td>
|
||||
<td>Plug solutions and endpoints into $f(x)$:</td>
|
||||
</tr>
|
||||
{% for candidate in candidates %}
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f({{ candidate }}) = {{values[loop.index - 1]}}$</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 5</td>
|
||||
<td>Grab the highest and lowest values</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>Your maximum value is ${{ maximum }}$</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>Your minimum value is ${{ newvar }}$</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Register
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form action="/register" method="post" id="form">
|
||||
<div class="form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="username" placeholder="Username" id="username" type="text">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input class="form-control" name="password" placeholder="Password" type="password">
|
||||
</div>
|
||||
<span id="availability"></span>
|
||||
<div class="form-group">
|
||||
<input class="form-control" name="confirmation" placeholder="confirm" type="password">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit" id="btn">Register</button>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
var username = document.getElementById("username");
|
||||
$(document).ready(function(){
|
||||
$('#btn').click(function (evt) {
|
||||
evt.preventDefault();
|
||||
$.get("/check", {username:username.value}, function(data){
|
||||
if (data == false){
|
||||
alert("Username is Taken")
|
||||
}
|
||||
else {
|
||||
$('#form').submit();
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Riemann
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<span>Function you would like to integrate:</span>
|
||||
<form action="/riemann" method="post">
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="function" placeholder="Function" type="text" id="function">
|
||||
</div>
|
||||
<p id="jp">Your Input Will Appear Here</p>
|
||||
<span>Range of values (a,b):</span>
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="lowerbound" placeholder="Lowerbound a" type="text" id="lowerbound">
|
||||
<input autocomplete="off" autofocus class="form-control" name="upperbound" placeholder="Upperbound b" type="text" id="upperbound">
|
||||
</div>
|
||||
<span>Amount of subintervals (how many rectangles?):</span>
|
||||
<div class="form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="subintervals" placeholder="Subintervals" type="text" id="subintervals">
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label><input type="radio" name="sumtype" checked value="1">Left Riemann Sum</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label><input type="radio" name="sumtype" value="2">Right Riemann Sum</label>
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Summation</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
let value = $("#function").val();
|
||||
$(document).ready(function(){
|
||||
$('#function').on('input', function() {
|
||||
let testvalue = $('#function').val();
|
||||
$('#jp').html("$f(x) = "+testvalue+"$");
|
||||
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title%}
|
||||
Summed
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<span>Approximating the integral of $f(x) = {{ value }}$ from ${{ lb }}$ to ${{ ub }}$ using ${{ si }}$ subintervals</span>
|
||||
<table class="table table-hover" action="optimized">
|
||||
<tbody>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 1</td>
|
||||
<td>Calculate $\Delta x$</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$\Delta x = {{ dx }}$</td>
|
||||
</tr>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 2</td>
|
||||
<td>Check values for $x_i$ (start at lowerbound a and add $\Delta x$ repeatedly)</td>
|
||||
</tr>
|
||||
{% for input in inputs %}
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f(x_{{ loop.index }}) = f({{ input }}) = {{ outputs[loop.index - 1] }}$</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 3</td>
|
||||
<td>Multiply $f(x_i)$ and $\Delta x$ for each subinterval</td>
|
||||
</tr>
|
||||
{% for rectangle in rectangles %}
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f(x_{{ loop.index}}) \Delta x = f({{ inputs[loop.index - 1]}})*{{ dx }} = {{ rectangle }}$</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 4</td>
|
||||
<td>Add up all products (rectangles) to get final approximation:</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>The integral of $f(x) = {{ value }}$ from ${{ lb }}$ to ${{ ub }}$ is approximately equal to ${{ result }}$</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title%}
|
||||
Summed
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<span>Approximating the integral of $f(x) = {{ value }}$ from ${{ lb }}$ to ${{ ub }}$ using ${{ si }}$ subintervals</span>
|
||||
<table class="table table-hover" action="optimized">
|
||||
<tbody>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 1</td>
|
||||
<td>Calculate $\Delta x$</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$\Delta x = {{ dx }}$</td>
|
||||
</tr>
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 2</td>
|
||||
<td>Check values for $x_i$ (start at lowerbound a and add $\Delta x$ repeatedly)</td>
|
||||
</tr>
|
||||
{% for input in inputs %}
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f(x_{{ loop.index - 1 }}) = f({{ input }}) = {{ outputs[loop.index - 1] }}$</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 3</td>
|
||||
<td>Multiply $f(x_i)$ and $\Delta x$ for each subinterval</td>
|
||||
</tr>
|
||||
{% for rectangle in rectangles %}
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>$f(x_{{ loop.index - 1 }}) \Delta x = f({{ inputs[loop.index - 1]}})*{{ dx }} = {{ rectangle }}$</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="bg-dark text-white">
|
||||
<td>Step 4</td>
|
||||
<td>Add up all products (rectangles) to get final approximation:</td>
|
||||
</tr>
|
||||
<tr class="table-secondary">
|
||||
<td></td>
|
||||
<td>The integral of $f(x) = {{ value }}$ from ${{ lb }}$ to ${{ ub }}$ is approximately equal to ${{ result }}$</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
import os
|
||||
|
||||
from cs50 import SQL
|
||||
from flask import Flask, flash, jsonify, redirect, render_template, request, session
|
||||
from flask_session import Session
|
||||
from tempfile import mkdtemp
|
||||
from werkzeug.exceptions import default_exceptions, HTTPException, InternalServerError
|
||||
from werkzeug.security import check_password_hash, generate_password_hash
|
||||
|
||||
from helpers import apology, login_required, lookup, usd
|
||||
|
||||
# Configure application
|
||||
app = Flask(__name__)
|
||||
|
||||
# Ensure templates are auto-reloaded
|
||||
app.config["TEMPLATES_AUTO_RELOAD"] = True
|
||||
|
||||
# Ensure responses aren't cached
|
||||
@app.after_request
|
||||
def after_request(response):
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
response.headers["Expires"] = 0
|
||||
response.headers["Pragma"] = "no-cache"
|
||||
return response
|
||||
|
||||
# Custom filter
|
||||
app.jinja_env.filters["usd"] = usd
|
||||
|
||||
# Configure session to use filesystem (instead of signed cookies)
|
||||
app.config["SESSION_FILE_DIR"] = mkdtemp()
|
||||
app.config["SESSION_PERMANENT"] = False
|
||||
app.config["SESSION_TYPE"] = "filesystem"
|
||||
Session(app)
|
||||
|
||||
# Configure CS50 Library to use SQLite database
|
||||
db = SQL("sqlite:///finance.db")
|
||||
|
||||
|
||||
@app.route("/")
|
||||
@login_required
|
||||
def index():
|
||||
"""Show portfolio of stocks"""
|
||||
rows = db.execute("SELECT * FROM users WHERE id = :id",
|
||||
id=session["user_id"])
|
||||
cash = int(rows[0]["cash"])
|
||||
stocks = db.execute("SELECT symbol, SUM(shares) as sum_shares FROM transactions WHERE id = :user_id GROUP BY symbol HAVING sum_shares > 0", user_id = session["user_id"])
|
||||
prices = list()
|
||||
values = list()
|
||||
for counter, stock in enumerate(stocks):
|
||||
quote = lookup(stocks[counter]["symbol"])
|
||||
prices.append(quote["price"])
|
||||
value = int(quote["price"] * stocks[counter]["sum_shares"])
|
||||
values.append(value)
|
||||
total_value = sum(values)
|
||||
return render_template("index.html", stocks = stocks, prices = prices, values = values, total_value = total_value, cash = cash)
|
||||
|
||||
|
||||
@app.route("/buy", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def buy():
|
||||
"""Buy shares of stock"""
|
||||
if request.method == "POST":
|
||||
|
||||
# Ensure quote and shares was submitted
|
||||
if not request.form.get("symbol"):
|
||||
return apology("must provide stock symbol", 400)
|
||||
if not request.form.get("shares"):
|
||||
return apology("must provide amount of shares", 400)
|
||||
|
||||
# Ensure shares is a positive integer
|
||||
shares = request.form.get("shares")
|
||||
if not shares.isdigit():
|
||||
return apology("must enter a positive integer", 400)
|
||||
|
||||
shares = int(request.form.get("shares"))
|
||||
# Get quote
|
||||
quote = lookup(request.form.get("symbol"))
|
||||
|
||||
if quote == None:
|
||||
return apology("please enter a valid quote", 400)
|
||||
|
||||
# Ensure cost is not too high
|
||||
share_price = quote["price"]
|
||||
cost = share_price * shares
|
||||
rows = db.execute("SELECT * FROM users WHERE id = :id",
|
||||
id=session["user_id"])
|
||||
cash = rows[0]["cash"]
|
||||
|
||||
if cost > cash:
|
||||
return apology("not enough cash")
|
||||
|
||||
symbol = quote["symbol"]
|
||||
# If successful update database cash amount
|
||||
db.execute("UPDATE users SET cash = cash - :cost WHERE id = :id", cost = cost, id = session["user_id"])
|
||||
# Add transaction to history
|
||||
db.execute("Insert INTO transactions (id, symbol, shares, price) VALUES(:id, :symbol, :shares, :cost)",
|
||||
id = session["user_id"], symbol = quote["symbol"], shares = shares, cost = cost)
|
||||
return redirect("/")
|
||||
|
||||
if quote == None:
|
||||
return apology("please enter a valid quote", 200)
|
||||
else:
|
||||
return render_template("buy.html")
|
||||
|
||||
@app.route("/trending", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def trending():
|
||||
stocks = db.execute("SELECT COUNT(id) as count_id, symbol, SUM(shares) as sum_shares FROM transactions GROUP BY symbol ORDER BY count_id DESC")
|
||||
prices = list()
|
||||
for counter, stock in enumerate(stocks):
|
||||
quote = lookup(stocks[counter]["symbol"])
|
||||
prices.append(quote["price"])
|
||||
return render_template("trending.html", stocks = stocks, prices = prices)
|
||||
|
||||
@app.route("/check", methods=["GET"])
|
||||
def check():
|
||||
"""Return true if username available, else false, in JSON format"""
|
||||
username = request.args.get("username")
|
||||
usernames = db.execute("SELECT username FROM users WHERE username = :username", username=username)
|
||||
if username and not usernames:
|
||||
return jsonify(True)
|
||||
else:
|
||||
return jsonify(False)
|
||||
|
||||
@app.route("/history")
|
||||
@login_required
|
||||
def history():
|
||||
"""Show history of transactions"""
|
||||
stocks = db.execute("SELECT symbol, price, date, shares FROM transactions WHERE id=:user_id", user_id=session["user_id"])
|
||||
values = list()
|
||||
boo = list()
|
||||
shares = list()
|
||||
for counter, stock in enumerate(stocks):
|
||||
price = stocks[counter]["price"]
|
||||
shares_count = stocks[counter]["shares"]
|
||||
if shares_count < 0:
|
||||
boo.append("Sold")
|
||||
price = price * (-1)
|
||||
shares_count = shares_count * (-1)
|
||||
shares.append(shares_count)
|
||||
values.append(price)
|
||||
else:
|
||||
boo.append("Bought")
|
||||
values.append(price)
|
||||
shares.append(shares_count)
|
||||
|
||||
return render_template("history.html", stocks = stocks, boo = boo, values = values, shares = shares)
|
||||
|
||||
|
||||
@app.route("/login", methods=["GET", "POST"])
|
||||
def login():
|
||||
"""Log user in"""
|
||||
|
||||
# Forget any user_id
|
||||
session.clear()
|
||||
|
||||
# User reached route via POST (as by submitting a form via POST)
|
||||
if request.method == "POST":
|
||||
|
||||
# Ensure username was submitted
|
||||
if not request.form.get("username"):
|
||||
return apology("must provide username", 403)
|
||||
|
||||
# Ensure password was submitted
|
||||
elif not request.form.get("password"):
|
||||
return apology("must provide password", 403)
|
||||
|
||||
# Query database for username
|
||||
rows = db.execute("SELECT * FROM users WHERE username = :username",
|
||||
username=request.form.get("username"))
|
||||
|
||||
# Ensure username exists and password is correct
|
||||
if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
|
||||
return apology("invalid username and/or password", 403)
|
||||
|
||||
# Remember which user has logged in
|
||||
session["user_id"] = rows[0]["id"]
|
||||
|
||||
# Redirect user to home page
|
||||
return redirect("/")
|
||||
|
||||
# User reached route via GET (as by clicking a link or via redirect)
|
||||
else:
|
||||
return render_template("login.html")
|
||||
|
||||
|
||||
@app.route("/logout")
|
||||
def logout():
|
||||
"""Log user out"""
|
||||
|
||||
# Forget any user_id
|
||||
session.clear()
|
||||
|
||||
# Redirect user to login form
|
||||
return redirect("/")
|
||||
|
||||
|
||||
@app.route("/quote", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def quote():
|
||||
"""Get stock quote."""
|
||||
|
||||
if request.method == "POST":
|
||||
|
||||
# Ensure quote was submitted
|
||||
if not request.form.get("symbol"):
|
||||
return apology("must provide stock symbol", 400)
|
||||
|
||||
quote = lookup(request.form.get("symbol"))
|
||||
|
||||
if quote == None:
|
||||
return apology("please enter a valid quote", 400)
|
||||
|
||||
return render_template("quoted.html", quote = quote)
|
||||
else:
|
||||
return render_template("quote.html")
|
||||
|
||||
|
||||
@app.route("/register", methods=["GET", "POST"])
|
||||
def register():
|
||||
"""Register user"""
|
||||
# Forget any user_id
|
||||
session.clear()
|
||||
|
||||
# User reached route via POST (as by submitting a form via POST)
|
||||
if request.method == "POST":
|
||||
|
||||
# Ensure username was submitted
|
||||
if not request.form.get("username"):
|
||||
return apology("must provide username", 400)
|
||||
|
||||
# Ensure password was submitted
|
||||
elif not request.form.get("password"):
|
||||
return apology("must provide password", 400)
|
||||
|
||||
# Ensure passwords match
|
||||
elif not request.form.get("password") == request.form.get("confirmation"):
|
||||
return apology("passwords must match", 400)
|
||||
|
||||
# Create hash for password
|
||||
hash = generate_password_hash(request.form.get("password"))
|
||||
|
||||
# Insert username into database
|
||||
result = db.execute("Insert INTO users (username, hash) VALUES(:username, :hash)", username = request.form.get("username"), hash = hash)
|
||||
|
||||
# Check if username is already taken
|
||||
if not result:
|
||||
return apology("Username has been taken", 400)
|
||||
|
||||
# Remember which user has logged in
|
||||
session["user_id"] = result
|
||||
|
||||
# Redirect user to home page
|
||||
return redirect("/")
|
||||
|
||||
# User reached route via GET (as by clicking a link or via redirect)
|
||||
else:
|
||||
return render_template("register.html")
|
||||
|
||||
|
||||
|
||||
@app.route("/sell", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def sell():
|
||||
"""Sell shares of stock"""
|
||||
stocks = db.execute("SELECT symbol, SUM(shares) as sum_shares FROM transactions WHERE id = :user_id GROUP BY symbol HAVING sum_shares > 0", user_id = session["user_id"])
|
||||
if request.method == "POST":
|
||||
# Ensure symbol and shares are submitted
|
||||
symbol = request.form.get("symbol")
|
||||
if not symbol:
|
||||
return apology("must choose a symbol", 400)
|
||||
shares = request.form.get("shares")
|
||||
if not shares:
|
||||
return apology("must enter shares amount", 400)
|
||||
|
||||
|
||||
# Ensure shares is a positive integer
|
||||
shares = int(request.form.get("shares"))
|
||||
if not type(shares) == int:
|
||||
return apology("must enter an integer", 400)
|
||||
if shares < 1 :
|
||||
return apology("must enter a positive integer", 400)
|
||||
|
||||
# Ensure proper amount of shares
|
||||
sum_shares = stocks[0]["sum_shares"]
|
||||
if shares > sum_shares:
|
||||
return apology("invalid shares amount", 400)
|
||||
|
||||
# Get quote
|
||||
quote = lookup(request.form.get("symbol"))
|
||||
|
||||
# Log loss of shares and increase in cash
|
||||
share_price = quote["price"]
|
||||
cost = share_price * shares * (-1)
|
||||
shares = shares * (-1)
|
||||
|
||||
symbol = quote["symbol"]
|
||||
# If successful update database cash amount
|
||||
db.execute("UPDATE users SET cash = cash - :cost WHERE id = :id", cost = cost, id = session["user_id"])
|
||||
# Add transaction to history
|
||||
db.execute("Insert INTO transactions (id, symbol, shares, price) VALUES(:id, :symbol, :shares, :cost)",
|
||||
id = session["user_id"], symbol = quote["symbol"], shares = shares, cost = cost)
|
||||
|
||||
# Redirect user to home page
|
||||
return redirect("/")
|
||||
else:
|
||||
return render_template("sell.html", stocks=stocks)
|
||||
|
||||
|
||||
def errorhandler(e):
|
||||
"""Handle error"""
|
||||
if not isinstance(e, HTTPException):
|
||||
e = InternalServerError()
|
||||
return apology(e.name, e.code)
|
||||
|
||||
|
||||
# Listen for errors
|
||||
for code in default_exceptions:
|
||||
app.errorhandler(code)(errorhandler)
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import requests
|
||||
import urllib.parse
|
||||
|
||||
from flask import redirect, render_template, request, session
|
||||
from functools import wraps
|
||||
|
||||
|
||||
def apology(message, code=400):
|
||||
"""Render message as an apology to user."""
|
||||
def escape(s):
|
||||
"""
|
||||
Escape special characters.
|
||||
|
||||
https://github.com/jacebrowning/memegen#special-characters
|
||||
"""
|
||||
for old, new in [("-", "--"), (" ", "-"), ("_", "__"), ("?", "~q"),
|
||||
("%", "~p"), ("#", "~h"), ("/", "~s"), ("\"", "''")]:
|
||||
s = s.replace(old, new)
|
||||
return s
|
||||
return render_template("apology.html", top=code, bottom=escape(message)), code
|
||||
|
||||
|
||||
def login_required(f):
|
||||
"""
|
||||
Decorate routes to require login.
|
||||
|
||||
http://flask.pocoo.org/docs/1.0/patterns/viewdecorators/
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if session.get("user_id") is None:
|
||||
return redirect("/login")
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
|
||||
def lookup(symbol):
|
||||
"""Look up quote for symbol."""
|
||||
|
||||
# Contact API
|
||||
try:
|
||||
response = requests.get(f"https://api.iextrading.com/1.0/stock/{urllib.parse.quote_plus(symbol)}/quote")
|
||||
response.raise_for_status()
|
||||
except requests.RequestException:
|
||||
return None
|
||||
|
||||
# Parse response
|
||||
try:
|
||||
quote = response.json()
|
||||
return {
|
||||
"name": quote["companyName"],
|
||||
"price": float(quote["latestPrice"]),
|
||||
"symbol": quote["symbol"]
|
||||
}
|
||||
except (KeyError, TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def usd(value):
|
||||
"""Format value as USD."""
|
||||
return f"${value:,.2f}"
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
cs50
|
||||
Flask
|
||||
Flask-Session
|
||||
requests
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
|
|
@ -0,0 +1,47 @@
|
|||
nav .navbar-brand
|
||||
{
|
||||
/* size for brand */
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
/* colors for brand */
|
||||
nav .navbar-brand .blue
|
||||
{
|
||||
color: #537fbe;
|
||||
}
|
||||
nav .navbar-brand .red
|
||||
{
|
||||
color: #ea433b;
|
||||
}
|
||||
nav .navbar-brand .yellow
|
||||
{
|
||||
color: #f5b82e;
|
||||
}
|
||||
nav .navbar-brand .green
|
||||
{
|
||||
color: #2e944b;
|
||||
}
|
||||
|
||||
main .form-control
|
||||
{
|
||||
/* center form controls */
|
||||
display: inline-block;
|
||||
|
||||
/* override Bootstrap's 100% width for form controls */
|
||||
width: auto;
|
||||
}
|
||||
|
||||
main
|
||||
{
|
||||
/* scroll horizontally as needed */
|
||||
overflow-x: auto;
|
||||
|
||||
/* center contents */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
main img
|
||||
{
|
||||
/* constrain images on small screens */
|
||||
max-width: 100%;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Apology
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<img alt="{{ top }}" class="border" src="http://memegen.link/custom/{{ top | urlencode }}/{{ bottom | urlencode }}.jpg?alt=https://i.imgur.com/CsCgN7Ll.png" title="{{ top }}">
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Buy
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form action="/buy" method="post">
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="symbol" placeholder="Stock Symbol" type="text">
|
||||
</div>
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="shares" placeholder="Shares" type="text">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Buy</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
History
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<table class="table" action="/history">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Bought/Sold</th>
|
||||
<th scope="col">Symbol</th>
|
||||
<th scope="col">Price</th>
|
||||
<th scope="col">Shares</th>
|
||||
<th scope="col">DateTime</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for stock in stocks %}
|
||||
<tr>
|
||||
<td>{{boo[loop.index - 1]}}</td>
|
||||
<td>{{stock.symbol}}</td>
|
||||
<td>{{values[loop.index - 1] | usd }}</td>
|
||||
<td>{{shares[loop.index - 1]}}</td>
|
||||
<td>{{stock.date}}</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Index
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<table class="table" action="/index">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Stock</th>
|
||||
<th scope="col">Shares</th>
|
||||
<th scope="col">Price</th>
|
||||
<th scope="col">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for stock in stocks %}
|
||||
<tr>
|
||||
<td>{{stock.symbol}}</td>
|
||||
<td>{{stock.sum_shares}}</td>
|
||||
<td>{{prices[loop.index - 1] | usd }}</td>
|
||||
<td>{{values[loop.index - 1] | usd }}</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>Current Cash:</td>
|
||||
<td>{{cash | usd }}</td>
|
||||
<td>Total Value:</td>
|
||||
<td>{{total_value | usd }}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- documentation at http://getbootstrap.com/docs/4.1/, alternative themes at https://bootswatch.com/ -->
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- https://favicon.io/emoji-favicons/money-mouth-face/ -->
|
||||
<link href="/static/favicon.ico" rel="icon">
|
||||
|
||||
<link href="/static/styles.css" rel="stylesheet">
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
|
||||
|
||||
<title>C$50 Finance: {% block title %}{% endblock %}</title>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light border">
|
||||
<a class="navbar-brand" href="/"><span class="blue">C</span><span class="red">$</span><span class="yellow">5</span><span class="green">0</span> <span class="red">Finance</span></a>
|
||||
<button aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#navbar" data-toggle="collapse" type="button">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbar">
|
||||
{% if session.user_id %}
|
||||
<ul class="navbar-nav mr-auto mt-2">
|
||||
<li class="nav-item"><a class="nav-link" href="/quote">Quote</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/buy">Buy</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/sell">Sell</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/history">History</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/trending">Trending</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto mt-2">
|
||||
<li class="nav-item"><a class="nav-link" href="/logout">Log Out</a></li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<ul class="navbar-nav ml-auto mt-2">
|
||||
<li class="nav-item"><a class="nav-link" href="/register">Register</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/login">Log In</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{% if get_flashed_messages() %}
|
||||
<header>
|
||||
<div class="alert alert-primary border text-center" role="alert">
|
||||
{{ get_flashed_messages() | join(" ") }}
|
||||
</div>
|
||||
</header>
|
||||
{% endif %}
|
||||
|
||||
<main class="container p-5">
|
||||
{% block main %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer class="small text-center text-muted">
|
||||
Data provided for free by <a href="https://iextrading.com/developer">IEX</a>. View <a href="https://iextrading.com/api-exhibit-a/">IEX’s Terms of Use</a>.
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Log In
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form action="/login" method="post">
|
||||
<div class="form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="username" placeholder="Username" type="text">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input class="form-control" name="password" placeholder="Password" type="password">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Log In</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Quote
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form action="/quote" method="post">
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="symbol" placeholder="Stock Symbol" type="text">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Get Quote</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Quoted
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div>
|
||||
{{ quote["symbol"] }}
|
||||
</div>
|
||||
<div>
|
||||
<p>The Price for {{ quote["name"] }} is {{ quote["price"] | usd }} per share</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Register
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form action="/register" method="post" id="form">
|
||||
<div class="form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="username" placeholder="Username" id="username" type="text">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input class="form-control" name="password" placeholder="Password" type="password">
|
||||
</div>
|
||||
<span id="availability"></span>
|
||||
<div class="form-group">
|
||||
<input class="form-control" name="confirmation" placeholder="confirm" type="password">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit" id="btn">Register</button>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
var username = document.getElementById("username");
|
||||
$(document).ready(function(){
|
||||
$('#btn').click(function (evt) {
|
||||
evt.preventDefault();
|
||||
$.get("/check", {username:username.value}, function(data){
|
||||
if (data == false){
|
||||
alert("Username is Taken")
|
||||
}
|
||||
else {
|
||||
$('#form').submit();
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Sell
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<form action="/sell" method="post">
|
||||
Stock to Sell:
|
||||
<div class="form-group">
|
||||
<select class="form-control" name="symbol">
|
||||
{% for stock in stocks %}
|
||||
<option value="{{stock.symbol}}">{{stock.symbol}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class = "form-group">
|
||||
<input autocomplete="off" autofocus class="form-control" name="shares" placeholder="Shares" type="text">
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Sell</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Trending
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<table class="table" action="/index">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">rank</th>
|
||||
<th scope="col">symbol</th>
|
||||
<th scope="col">price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for stock in stocks %}
|
||||
<tr>
|
||||
<td>{{loop.index}}</td>
|
||||
<td>{{stock.symbol}}</td>
|
||||
<td>{{prices[loop.index - 1] | usd }}</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
#include <cs50.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
int check_length(long int n);
|
||||
int check_digit(long int num, int length, int n);
|
||||
bool luhn_alg(long int num, int length);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// setup variables
|
||||
long int num = 0;
|
||||
int length = 0;
|
||||
string type = "";
|
||||
bool check = false;
|
||||
|
||||
do
|
||||
{
|
||||
// get the number and setup variable to check if valid
|
||||
num = get_long("number:");
|
||||
length = check_length(num);
|
||||
int digit1 = check_digit(num, length, 1);
|
||||
int digit2 = check_digit(num, length, 2);
|
||||
bool luhn = luhn_alg(num, length);
|
||||
if (luhn == false)
|
||||
{
|
||||
printf("INVALID\n");
|
||||
break;
|
||||
}
|
||||
|
||||
//checking all possible lengths, looking at beginning digits to determine card type if valid
|
||||
if (length == 13)
|
||||
{
|
||||
if (digit1 == 4)
|
||||
{
|
||||
type = "VISA";
|
||||
check = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("INVALID\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (length == 15)
|
||||
{
|
||||
if (digit1 == 3 && (digit2 == 4 || digit2 == 7))
|
||||
{
|
||||
type = "AMEX";
|
||||
check = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("INVALID\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (length == 16)
|
||||
{
|
||||
if (digit1 == 5 && digit2 > 0 && digit2 < 6)
|
||||
{
|
||||
type = "MASTERCARD";
|
||||
check = true;
|
||||
}
|
||||
|
||||
|
||||
else if (digit1 == 4)
|
||||
{
|
||||
type = "VISA";
|
||||
check = true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("INVALID\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("INVALID\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
while (check == false);
|
||||
printf("%s\n", type);
|
||||
|
||||
}
|
||||
|
||||
//function to check the length of card number given
|
||||
int check_length(long int num)
|
||||
{
|
||||
int count = 0;
|
||||
do
|
||||
{
|
||||
num = num / 10;
|
||||
count = count + 1;
|
||||
}
|
||||
while (num > 0);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
//function to check the nth digit of the card number given
|
||||
int check_digit(long int num, int length, int n)
|
||||
{
|
||||
|
||||
long int digit = num / pow(10, length - n);
|
||||
digit = digit % 10;
|
||||
digit = (int)digit;
|
||||
return digit;
|
||||
|
||||
}
|
||||
|
||||
// function to check Luhn's algorithm
|
||||
bool luhn_alg(long int num, int length)
|
||||
{
|
||||
int sum = 0;
|
||||
int count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// get the digit, multiply by 2, add up digits, add to sum for every other digit starting at 2nd to last
|
||||
int temp = check_digit(num, length, length - (count + 1));
|
||||
temp = temp * 2;
|
||||
int templength = check_length(temp);
|
||||
int tempdigit1 = check_digit(temp, templength, 1);
|
||||
int tempdigit2 = check_digit(temp, templength, 2);
|
||||
sum = sum + tempdigit1;
|
||||
sum = sum + tempdigit2;
|
||||
count = count + 2;
|
||||
}
|
||||
while (count < length);
|
||||
count = 0; //reset count
|
||||
do
|
||||
{
|
||||
int temp = check_digit(num, length, length - count);
|
||||
sum = sum + temp;
|
||||
count = count + 2;
|
||||
}
|
||||
while (count < length);
|
||||
|
||||
if (sum % 10 == 0)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#include <cs50.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int get_int_range(string prompt); // making a prototype for our get int function
|
||||
void print_lots(string character,int n); // prototype for printing repeated characters in a line
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int height = get_int_range("Height between 1 and 8:");
|
||||
|
||||
for (int k=0; k<height; k++)
|
||||
{
|
||||
// print characters in proper order
|
||||
print_lots(" ",height - k - 1);
|
||||
print_lots("#",k+1);
|
||||
printf(" ");
|
||||
print_lots("#",k+1);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int get_int_range(string prompt) // define function to get an int in a range
|
||||
{
|
||||
int n;
|
||||
do
|
||||
{
|
||||
n = get_int("%s", prompt);
|
||||
}
|
||||
while (n < 1 || n>8);
|
||||
return n;
|
||||
}
|
||||
|
||||
void print_lots(string character,int n) // define a function to print the same character a bunch
|
||||
{
|
||||
for(int i=0; i<n;i++)
|
||||
{
|
||||
printf("%s", character);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#include <cs50.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, string argv[])
|
||||
{
|
||||
//Validate the key
|
||||
if (argc != 2)
|
||||
{
|
||||
printf("Usage: ./caesar key\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
string key = argv[1];
|
||||
int intkey = atoi(argv[1]);
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
// Iterate over length of key, checking for non-digits
|
||||
for (int i = 0, n = strlen(key); i < n; i++)
|
||||
{
|
||||
if (isdigit(key[i]) == false)
|
||||
{
|
||||
printf("Usage: ./caesar key\n");
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Setup cipher
|
||||
string plaintext = get_string("plaintext: ");
|
||||
printf("ciphertext: ");
|
||||
// iterate over input of plaintext, seperating into uppor or lower cases, then implementing cypher
|
||||
for (int i = 0, n = strlen(plaintext); i < n; i++)
|
||||
{
|
||||
char c = plaintext[i];
|
||||
char temp = 'a';
|
||||
if (isalpha(c))
|
||||
{
|
||||
if (isupper(c))
|
||||
{
|
||||
temp = (((plaintext[i] - 'A') + intkey) % 26) + 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = (((plaintext[i] - 'a') + intkey) % 26) + 'a';
|
||||
}
|
||||
printf("%c", temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%c", c);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
#include <cs50.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
int shift(char c);
|
||||
|
||||
int main(int argc, string argv[])
|
||||
{
|
||||
//Validate the key
|
||||
string key = argv[1];
|
||||
if (argc != 2)
|
||||
{
|
||||
printf("Usage: ./vigenere keyword\n");
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Iterate over length of key, checking for non-digits
|
||||
for (int i = 0, n = strlen(key); i < n; i++)
|
||||
{
|
||||
if (isalpha(key[i]) == false)
|
||||
{
|
||||
printf("Usage: ./vigenere keyword\n");
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Setup cipher
|
||||
int length = strlen(key);
|
||||
int k = 0;
|
||||
string plaintext = get_string("plaintext: ");
|
||||
printf("ciphertext: ");
|
||||
// iterate over input of plaintext, seperating into uppor or lower cases, then implementing cypher
|
||||
for (int i = 0, n = strlen(plaintext); i < n;i++)
|
||||
{
|
||||
char c = plaintext[i];
|
||||
char temp = 'a';
|
||||
int intkey = shift(argv[1][(k % length)]);
|
||||
if (isalpha(c))
|
||||
{
|
||||
if (isupper(c))
|
||||
{
|
||||
temp = (((plaintext[i] - 'A') + intkey) % 26) + 'A';
|
||||
k++;
|
||||
}
|
||||
else if (islower(c))
|
||||
{
|
||||
temp = (((plaintext[i] - 'a') + intkey) % 26) + 'a';
|
||||
k++;
|
||||
}
|
||||
printf("%c", temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%c", c);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
//Tells us how much to shift based on individual characters
|
||||
int shift(char c)
|
||||
{
|
||||
if isupper(c)
|
||||
{
|
||||
int temp = c - 65;
|
||||
return(temp);
|
||||
}
|
||||
else if islower(c)
|
||||
{
|
||||
int temp = c - 97;
|
||||
return(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
// Copies a BMP file
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bmp.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// ensure proper usage
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("Usage: copy infile outfile\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// remember filenames
|
||||
char *infile = argv[1];
|
||||
char *outfile = argv[2];
|
||||
|
||||
// open input file
|
||||
FILE *inptr = fopen(infile, "r");
|
||||
if (inptr == NULL)
|
||||
{
|
||||
printf("Could not open %s.\n", infile);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// open output file
|
||||
FILE *outptr = fopen(outfile, "w");
|
||||
if (outptr == NULL)
|
||||
{
|
||||
fclose(inptr);
|
||||
printf("Could not create %s.\n", outfile);
|
||||
return 3;
|
||||
}
|
||||
|
||||
// read infile's BITMAPFILEHEADER
|
||||
BITMAPFILEHEADER bf;
|
||||
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
|
||||
|
||||
// read infile's BITMAPINFOHEADER
|
||||
BITMAPINFOHEADER bi;
|
||||
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
|
||||
|
||||
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
|
||||
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
|
||||
bi.biBitCount != 24 || bi.biCompression != 0)
|
||||
{
|
||||
fclose(outptr);
|
||||
fclose(inptr);
|
||||
printf("Unsupported file format.\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
// write outfile's BITMAPFILEHEADER
|
||||
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
|
||||
|
||||
// write outfile's BITMAPINFOHEADER
|
||||
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
|
||||
|
||||
// determine padding for scanlines
|
||||
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
|
||||
|
||||
// iterate over infile's scanlines
|
||||
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
|
||||
{
|
||||
// iterate over pixels in scanline
|
||||
for (int j = 0; j < bi.biWidth; j++)
|
||||
{
|
||||
// temporary storage
|
||||
RGBTRIPLE triple;
|
||||
|
||||
// read RGB triple from infile
|
||||
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
|
||||
|
||||
if (triple.rgbtRed > 240)
|
||||
{
|
||||
triple.rgbtRed = 00;
|
||||
triple.rgbtBlue = 00;
|
||||
triple.rgbtGreen = 00;
|
||||
}
|
||||
|
||||
|
||||
// write RGB triple to outfile
|
||||
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
|
||||
}
|
||||
|
||||
// skip over padding, if any
|
||||
fseek(inptr, padding, SEEK_CUR);
|
||||
|
||||
// then add it back (to demonstrate how)
|
||||
for (int k = 0; k < padding; k++)
|
||||
{
|
||||
fputc(0x00, outptr);
|
||||
}
|
||||
}
|
||||
|
||||
// close infile
|
||||
fclose(inptr);
|
||||
|
||||
// close outfile
|
||||
fclose(outptr);
|
||||
|
||||
// success
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cs50.h>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// check if valid argument counter
|
||||
if (argc != 2)
|
||||
{
|
||||
printf("Usage: ./recover file.jpg\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
// initialize input as variable
|
||||
FILE *inptr = fopen(argv[1], "r");
|
||||
|
||||
// open up the file and check if valid file
|
||||
if ( inptr == NULL )
|
||||
{
|
||||
printf("Could not open file\n");
|
||||
return(2);
|
||||
}
|
||||
|
||||
//global variables
|
||||
unsigned char buffer[512];
|
||||
FILE *img = NULL;
|
||||
int counter = 0;
|
||||
char filename[8];
|
||||
|
||||
//Setup loop
|
||||
while (true)
|
||||
{
|
||||
int read = fread(&buffer, 512, 1, inptr);
|
||||
// break if at EOF
|
||||
if (read != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// check if at start of file
|
||||
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
|
||||
{
|
||||
// If not at first run, close last file
|
||||
if (img != NULL)
|
||||
{
|
||||
fclose(img);
|
||||
}
|
||||
// open up new file since we are at start
|
||||
sprintf(filename, "%03i.jpg", counter);
|
||||
img = fopen(filename, "w");
|
||||
counter ++;
|
||||
}
|
||||
// only write to the file if we are not in the first run!!!!
|
||||
if (img != NULL)
|
||||
{
|
||||
fwrite(&buffer, 512, 1, img);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
fclose(img);
|
||||
fclose(inptr);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// BMP-related data types based on Microsoft's own
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// aliases for C/C++ primitive data types
|
||||
// https://msdn.microsoft.com/en-us/library/cc230309.aspx
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint32_t DWORD;
|
||||
typedef int32_t LONG;
|
||||
typedef uint16_t WORD;
|
||||
|
||||
// information about the type, size, and layout of a file
|
||||
// https://msdn.microsoft.com/en-us/library/dd183374(v=vs.85).aspx
|
||||
typedef struct
|
||||
{
|
||||
WORD bfType;
|
||||
DWORD bfSize;
|
||||
WORD bfReserved1;
|
||||
WORD bfReserved2;
|
||||
DWORD bfOffBits;
|
||||
} __attribute__((__packed__))
|
||||
BITMAPFILEHEADER;
|
||||
|
||||
// information about the dimensions and color format
|
||||
// https://msdn.microsoft.com/en-us/library/dd183376(v=vs.85).aspx
|
||||
typedef struct
|
||||
{
|
||||
DWORD biSize;
|
||||
LONG biWidth;
|
||||
LONG biHeight;
|
||||
WORD biPlanes;
|
||||
WORD biBitCount;
|
||||
DWORD biCompression;
|
||||
DWORD biSizeImage;
|
||||
LONG biXPelsPerMeter;
|
||||
LONG biYPelsPerMeter;
|
||||
DWORD biClrUsed;
|
||||
DWORD biClrImportant;
|
||||
} __attribute__((__packed__))
|
||||
BITMAPINFOHEADER;
|
||||
|
||||
// relative intensities of red, green, and blue
|
||||
// https://msdn.microsoft.com/en-us/library/dd162939(v=vs.85).aspx
|
||||
typedef struct
|
||||
{
|
||||
BYTE rgbtBlue;
|
||||
BYTE rgbtGreen;
|
||||
BYTE rgbtRed;
|
||||
} __attribute__((__packed__))
|
||||
RGBTRIPLE;
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// Copies a BMP file
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bmp.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// ensure proper usage
|
||||
if (argc != 3)
|
||||
{
|
||||
fprintf(stderr, "Usage: copy infile outfile\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// remember filenames
|
||||
char *infile = argv[1];
|
||||
char *outfile = argv[2];
|
||||
|
||||
// open input file
|
||||
FILE *inptr = fopen(infile, "r");
|
||||
if (inptr == NULL)
|
||||
{
|
||||
fprintf(stderr, "Could not open %s.\n", infile);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// open output file
|
||||
FILE *outptr = fopen(outfile, "w");
|
||||
if (outptr == NULL)
|
||||
{
|
||||
fclose(inptr);
|
||||
fprintf(stderr, "Could not create %s.\n", outfile);
|
||||
return 3;
|
||||
}
|
||||
|
||||
// read infile's BITMAPFILEHEADER
|
||||
BITMAPFILEHEADER bf;
|
||||
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
|
||||
|
||||
// read infile's BITMAPINFOHEADER
|
||||
BITMAPINFOHEADER bi;
|
||||
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
|
||||
|
||||
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
|
||||
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
|
||||
bi.biBitCount != 24 || bi.biCompression != 0)
|
||||
{
|
||||
fclose(outptr);
|
||||
fclose(inptr);
|
||||
fprintf(stderr, "Unsupported file format.\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
// write outfile's BITMAPFILEHEADER
|
||||
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
|
||||
|
||||
// write outfile's BITMAPINFOHEADER
|
||||
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
|
||||
|
||||
// determine padding for scanlines
|
||||
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
|
||||
|
||||
// iterate over infile's scanlines
|
||||
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
|
||||
{
|
||||
// iterate over pixels in scanline
|
||||
for (int j = 0; j < bi.biWidth; j++)
|
||||
{
|
||||
// temporary storage
|
||||
RGBTRIPLE triple;
|
||||
|
||||
// read RGB triple from infile
|
||||
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
|
||||
|
||||
// write RGB triple to outfile
|
||||
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
|
||||
}
|
||||
|
||||
// skip over padding, if any
|
||||
fseek(inptr, padding, SEEK_CUR);
|
||||
|
||||
// then add it back (to demonstrate how)
|
||||
for (int k = 0; k < padding; k++)
|
||||
{
|
||||
fputc(0x00, outptr);
|
||||
}
|
||||
}
|
||||
|
||||
// close infile
|
||||
fclose(inptr);
|
||||
|
||||
// close outfile
|
||||
fclose(outptr);
|
||||
|
||||
// success
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 486 B |
|
After Width: | Height: | Size: 174 B |
|
|
@ -0,0 +1,135 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "bmp.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// ensure proper usage
|
||||
if (argc != 4)
|
||||
{
|
||||
fprintf(stderr, "Usage: ./resize n infile outfile\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// remember resize factor n
|
||||
int n = atoi(argv[1]);
|
||||
|
||||
// remember filenames
|
||||
char *infile = argv[2];
|
||||
char *outfile = argv[3];
|
||||
|
||||
// open input file
|
||||
FILE *inptr = fopen(infile, "r");
|
||||
if (inptr == NULL)
|
||||
{
|
||||
fprintf(stderr, "Could not open %s.\n", infile);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// open output file
|
||||
FILE *outptr = fopen(outfile, "w");
|
||||
if (outptr == NULL)
|
||||
{
|
||||
fclose(inptr);
|
||||
fprintf(stderr, "Could not create %s.\n", outfile);
|
||||
return 3;
|
||||
}
|
||||
|
||||
// read infile's BITMAPFILEHEADER
|
||||
BITMAPFILEHEADER bf;
|
||||
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
|
||||
|
||||
// read infile's BITMAPINFOHEADER
|
||||
BITMAPINFOHEADER bi;
|
||||
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
|
||||
|
||||
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
|
||||
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
|
||||
bi.biBitCount != 24 || bi.biCompression != 0)
|
||||
{
|
||||
fclose(outptr);
|
||||
fclose(inptr);
|
||||
fprintf(stderr, "Unsupported file format.\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
// store all old header info which we will change
|
||||
int oldWidth = bi.biWidth;
|
||||
int oldPadding = (4 - (oldWidth * sizeof(RGBTRIPLE)) % 4) % 4;
|
||||
int oldHeight = bi.biHeight;
|
||||
int oldSizeImage = bi.biSizeImage;
|
||||
int oldSize = bf.bfSize;
|
||||
|
||||
// calculate and store new header info
|
||||
int newWidth = bi.biWidth * n;
|
||||
int newPadding = (4 - (newWidth * sizeof(RGBTRIPLE)) % 4) % 4;
|
||||
int newHeight = bi.biHeight * n;
|
||||
int newSizeImage = ((((newWidth * bi.biBitCount) + 31) & ~31) / 8) * abs(newHeight);
|
||||
int newSize = 54 + newWidth * abs(newHeight) * 3 + abs(newHeight) * newPadding;
|
||||
|
||||
// update header info
|
||||
bi.biWidth = newWidth;
|
||||
bi.biHeight = newHeight;
|
||||
bi.biSizeImage = newSizeImage;
|
||||
bf.bfSize = newSize;
|
||||
|
||||
|
||||
// write outfile's BITMAPFILEHEADER
|
||||
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
|
||||
|
||||
// write outfile's BITMAPINFOHEADER
|
||||
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
|
||||
|
||||
|
||||
// Go through reading each scanline
|
||||
for (int i = 0; i < abs(oldHeight); i++)
|
||||
{
|
||||
// process of reading and writing the line n times
|
||||
for (int j = 0; j < n; j++)
|
||||
{
|
||||
// go through each pixel to copy and write n times
|
||||
for (int k = 0; k < oldWidth; k++)
|
||||
{
|
||||
// temporary triple
|
||||
RGBTRIPLE triple;
|
||||
|
||||
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
|
||||
|
||||
// Write the triple N times
|
||||
for (int l = 0; l < n; l++)
|
||||
{
|
||||
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
|
||||
}
|
||||
}
|
||||
|
||||
// add newPadding
|
||||
for (int k = 0; k < newPadding; k++)
|
||||
{
|
||||
fputc(0x00, outptr);
|
||||
}
|
||||
|
||||
// Check whether we are on last one, and if not reset the file pointer
|
||||
if (j < n - 1)
|
||||
{
|
||||
fseek(inptr, -oldWidth * sizeof(RGBTRIPLE), SEEK_CUR);
|
||||
}
|
||||
}
|
||||
// skip reading the old padding once we are done reading/writing and ready to
|
||||
// move to the next line
|
||||
fseek(inptr, oldPadding, SEEK_CUR);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// close infile
|
||||
fclose(inptr);
|
||||
|
||||
// close outfile
|
||||
fclose(outptr);
|
||||
|
||||
// success
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 90 B |
|
After Width: | Height: | Size: 246 B |
|
|
@ -0,0 +1,4 @@
|
|||
speller:
|
||||
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c
|
||||
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c
|
||||
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o speller speller.o dictionary.o
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
cat
|
||||
caterpillar
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
// Implements a dictionary's functionality
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h> // for isupper/islower
|
||||
|
||||
#include "dictionary.h"
|
||||
|
||||
// global variable to hold word count
|
||||
int words = 0;
|
||||
// Represents number of children for each node in a trie
|
||||
#define N 27
|
||||
|
||||
// Represents a node in a trie
|
||||
typedef struct node
|
||||
{
|
||||
bool is_word;
|
||||
struct node *children[N];
|
||||
}
|
||||
node;
|
||||
|
||||
// Represents a trie
|
||||
node *root;
|
||||
|
||||
// Loads dictionary into memory, returning true if successful else false
|
||||
bool load(const char *dictionary)
|
||||
{
|
||||
// Initialize trie
|
||||
root = malloc(sizeof(node));
|
||||
if (root == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
root->is_word = false;
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
root->children[i] = NULL;
|
||||
}
|
||||
|
||||
// Open dictionary
|
||||
FILE *file = fopen(dictionary, "r");
|
||||
if (file == NULL)
|
||||
{
|
||||
unload();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Buffer for a word
|
||||
char word[LENGTH + 1];
|
||||
|
||||
// Insert words into trie
|
||||
while (fscanf(file, "%s", word) != EOF)
|
||||
{
|
||||
// write word into buffer
|
||||
fwrite(word, LENGTH, 1, file);
|
||||
|
||||
// initialize a pointer to traverse the trie and have it point to root
|
||||
node *trav = root;
|
||||
|
||||
// iterate through each letter in the string
|
||||
for (int i = 0, len = strlen(word); i < len; i++)
|
||||
{
|
||||
// convert letter to number 1-27
|
||||
int childnum = word[i];
|
||||
if (childnum == 39)
|
||||
{
|
||||
childnum = 26;
|
||||
}
|
||||
else
|
||||
{
|
||||
childnum = word[i] - 97;
|
||||
}
|
||||
|
||||
// check if the c value points to null
|
||||
if (trav->children[childnum] == NULL)
|
||||
{
|
||||
// make a new node and initialize values
|
||||
node *fresh;
|
||||
fresh = malloc(sizeof(node));
|
||||
if (fresh == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fresh->is_word = false;
|
||||
for (int k = 0; k < N; k++)
|
||||
{
|
||||
fresh->children[k] = NULL;
|
||||
}
|
||||
|
||||
// have last node point to this
|
||||
trav->children[childnum] = fresh;
|
||||
|
||||
// point trav to this new node
|
||||
trav = fresh;
|
||||
}
|
||||
|
||||
// for if there exists a node already
|
||||
else
|
||||
{
|
||||
// have trav point to the non null node
|
||||
trav = trav->children[childnum];
|
||||
}
|
||||
}
|
||||
|
||||
// mark as end of a letter and increase word count
|
||||
trav->is_word = true;
|
||||
words ++;
|
||||
}
|
||||
|
||||
// Close dictionary
|
||||
fclose(file);
|
||||
|
||||
// Indicate success
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns number of words in dictionary if loaded else 0 if not yet loaded
|
||||
unsigned int size(void)
|
||||
{
|
||||
return words;
|
||||
}
|
||||
|
||||
// Returns true if word is in dictionary else false
|
||||
bool check(const char *word)
|
||||
{
|
||||
// create pointer trav starting at root to traverse the trie (root is itself a pointer so just set equal)
|
||||
node *trav = root;
|
||||
|
||||
// iterate through each letter in the word
|
||||
for (int i=0, n = strlen(word); i < n; i++)
|
||||
{
|
||||
// convert letter to index number
|
||||
int childnum;
|
||||
if (isupper(word[i]))
|
||||
{
|
||||
childnum = word[i] - 65;
|
||||
}
|
||||
else if (islower(word[i]))
|
||||
{
|
||||
childnum = word[i] - 97;
|
||||
}
|
||||
else
|
||||
{
|
||||
childnum = 26;
|
||||
}
|
||||
|
||||
// point trav at the corrosponding node
|
||||
trav = trav->children[childnum];
|
||||
|
||||
// Deal with the case where we ran out of nodes to follow
|
||||
if (!trav)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// when we have done all the letters, see if we are at a word
|
||||
if (trav->is_word)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// recursive function which iterates through each letter in a node, if not null letter then do it again on corrosponding node, and at
|
||||
// end of iteration frees the node
|
||||
|
||||
void clear(node *ptr)
|
||||
{
|
||||
for (int i = 0; i<27; i++)
|
||||
{
|
||||
if (ptr->children[i] != NULL)
|
||||
{
|
||||
clear(ptr->children[i]);
|
||||
}
|
||||
}
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
// Unloads dictionary from memory, returning true if successful else false
|
||||
bool unload(void)
|
||||
{
|
||||
clear(root);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// Declares a dictionary's functionality
|
||||
|
||||
#ifndef DICTIONARY_H
|
||||
#define DICTIONARY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
// Maximum length for a word
|
||||
// (e.g., pneumonoultramicroscopicsilicovolcanoconiosis)
|
||||
#define LENGTH 45
|
||||
|
||||
// Prototypes
|
||||
bool load(const char *dictionary);
|
||||
unsigned int size(void);
|
||||
bool check(const char *word);
|
||||
bool unload();
|
||||
|
||||
#endif // DICTIONARY_H
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
|
||||
MISSPELLED WORDS
|
||||
|
||||
Gutenberg's
|
||||
Alice's
|
||||
eBook
|
||||
eBook
|
||||
org
|
||||
Alice's
|
||||
EBook
|
||||
EBOOK
|
||||
ALICE'S
|
||||
ALICE'S
|
||||
MARMALADE'
|
||||
Antipathies
|
||||
Dinah'll
|
||||
Alice's
|
||||
ME'
|
||||
not'
|
||||
ME'
|
||||
ALICE'S
|
||||
ESQ
|
||||
HEARTHRUG
|
||||
ALICE'S
|
||||
skurried
|
||||
O
|
||||
O
|
||||
O
|
||||
Ou
|
||||
chatte
|
||||
better'
|
||||
Morcar
|
||||
Morcar
|
||||
Stigand
|
||||
Atheling
|
||||
William's
|
||||
Normans
|
||||
thimble'
|
||||
C
|
||||
D
|
||||
Mouse's
|
||||
Dinah's
|
||||
naturedly
|
||||
W
|
||||
RABBIT'
|
||||
Dinah'll
|
||||
pleasanter
|
||||
Alice's
|
||||
won't'
|
||||
yer
|
||||
yer
|
||||
arrum
|
||||
yer
|
||||
yer
|
||||
Bill's
|
||||
Bill's
|
||||
Bill's
|
||||
Bill's
|
||||
barrowful
|
||||
barrowful
|
||||
V
|
||||
sir'
|
||||
yawned
|
||||
Footman's
|
||||
nose'
|
||||
Hatter's
|
||||
Alice's
|
||||
Lacie
|
||||
Sh
|
||||
sh
|
||||
were'
|
||||
M
|
||||
M
|
||||
M
|
||||
everything's
|
||||
beheaded
|
||||
King's
|
||||
processions
|
||||
rosetree
|
||||
beheaded
|
||||
croqueted
|
||||
croqueting
|
||||
executioner's
|
||||
King's
|
||||
beheaded
|
||||
Alice's
|
||||
Everything's
|
||||
Alice's
|
||||
Alice's
|
||||
game's
|
||||
Tis
|
||||
tis
|
||||
tis
|
||||
Alice's
|
||||
m
|
||||
Alice's
|
||||
ordered'
|
||||
Hjckrrh
|
||||
mayn't
|
||||
uglifying
|
||||
Seaography
|
||||
X
|
||||
never'
|
||||
dinn
|
||||
Dinn
|
||||
yawned
|
||||
TIS
|
||||
Tis
|
||||
Hm
|
||||
ootiful
|
||||
oop
|
||||
ootiful
|
||||
oop
|
||||
oop
|
||||
e
|
||||
e
|
||||
ootiful
|
||||
oop
|
||||
ootiful
|
||||
oop
|
||||
oop
|
||||
e
|
||||
e
|
||||
beauti
|
||||
FUL
|
||||
oop
|
||||
e
|
||||
e
|
||||
men'
|
||||
slates'll
|
||||
T
|
||||
Alice's
|
||||
jurymen
|
||||
jurymen
|
||||
jurymen
|
||||
jurymen
|
||||
teacups
|
||||
teacups
|
||||
Gutenberg's
|
||||
Alice's
|
||||
EBOOK
|
||||
ALICE'S
|
||||
txt
|
||||
http
|
||||
org
|
||||
tm
|
||||
tm
|
||||
eBooks
|
||||
eBook
|
||||
eBook
|
||||
eBooks
|
||||
tm
|
||||
tm
|
||||
http
|
||||
org
|
||||
tm
|
||||
tm
|
||||
tm
|
||||
tm
|
||||
E
|
||||
B
|
||||
tm
|
||||
C
|
||||
tm
|
||||
tm
|
||||
E
|
||||
C
|
||||
PGLAF
|
||||
tm
|
||||
tm
|
||||
tm
|
||||
tm
|
||||
tm
|
||||
D
|
||||
tm
|
||||
E
|
||||
E
|
||||
tm
|
||||
tm
|
||||
eBook
|
||||
eBook
|
||||
org
|
||||
E
|
||||
tm
|
||||
E
|
||||
E
|
||||
tm
|
||||
E
|
||||
E
|
||||
E
|
||||
tm
|
||||
E
|
||||
E
|
||||
tm
|
||||
E
|
||||
tm
|
||||
tm
|
||||
E
|
||||
E
|
||||
tm
|
||||
E
|
||||
nonproprietary
|
||||
tm
|
||||
tm
|
||||
org
|
||||
tm
|
||||
E
|
||||
E
|
||||
tm
|
||||
E
|
||||
E
|
||||
E
|
||||
tm
|
||||
tm
|
||||
tm
|
||||
e
|
||||
s
|
||||
tm
|
||||
tm
|
||||
F
|
||||
tm
|
||||
E
|
||||
tm
|
||||
tm
|
||||
F
|
||||
F
|
||||
tm
|
||||
tm
|
||||
F
|
||||
F
|
||||
tm
|
||||
tm
|
||||
F
|
||||
F
|
||||
F
|
||||
IS'
|
||||
MERCHANTIBILITY
|
||||
F
|
||||
unenforceability
|
||||
F
|
||||
tm
|
||||
tm
|
||||
tm
|
||||
b
|
||||
tm
|
||||
c
|
||||
tm
|
||||
tm
|
||||
tm's
|
||||
tm
|
||||
tm
|
||||
http
|
||||
pglaf
|
||||
org
|
||||
c
|
||||
c
|
||||
http
|
||||
pglaf
|
||||
org
|
||||
U
|
||||
S
|
||||
Melan
|
||||
S
|
||||
pglaf
|
||||
org
|
||||
http
|
||||
pglaf
|
||||
org
|
||||
B
|
||||
Newby
|
||||
gbnewby
|
||||
pglaf
|
||||
org
|
||||
tm
|
||||
http
|
||||
pglaf
|
||||
org
|
||||
U
|
||||
S
|
||||
http
|
||||
pglaf
|
||||
org
|
||||
tm
|
||||
S
|
||||
tm
|
||||
tm
|
||||
eBooks
|
||||
tm
|
||||
eBooks
|
||||
U
|
||||
S
|
||||
eBooks
|
||||
PG
|
||||
http
|
||||
org
|
||||
tm
|
||||
eBooks
|
||||
eBooks
|
||||
|
||||
WORDS MISSPELLED: 295
|
||||
WORDS IN DICTIONARY: 143091
|
||||
WORDS IN TEXT: 29758
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
MISSPELLED WORDS
|
||||
|
||||
|
||||
WORDS MISSPELLED: 0
|
||||
WORDS IN DICTIONARY: 143091
|
||||
WORDS IN TEXT: 6
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
MISSPELLED WORDS
|
||||
|
||||
USConstitution
|
||||
http
|
||||
usconstitution
|
||||
const
|
||||
html
|
||||
tempore
|
||||
Impeachments
|
||||
Nays
|
||||
Nays
|
||||
repassed
|
||||
Piracies
|
||||
Felonies
|
||||
attainted
|
||||
Langdon
|
||||
Gilman
|
||||
Brearley
|
||||
Mifflin
|
||||
Clymer
|
||||
Fitzsimons
|
||||
Jared
|
||||
Gouvernour
|
||||
McHenry
|
||||
Jenifer
|
||||
Blount
|
||||
Spaight
|
||||
Cotesworth
|
||||
tempore
|
||||
tempore
|
||||
tempore
|
||||
tempore
|
||||
|
||||
WORDS MISSPELLED: 30
|
||||
WORDS IN DICTIONARY: 143091
|
||||
WORDS IN TEXT: 7573
|
||||
|
|
@ -0,0 +1,942 @@
|
|||
|
||||
MISSPELLED WORDS
|
||||
|
||||
Etext
|
||||
txt
|
||||
Etext
|
||||
etexts
|
||||
txt
|
||||
txt
|
||||
etext
|
||||
hr
|
||||
Etext
|
||||
x
|
||||
IBC
|
||||
IBC
|
||||
IBC
|
||||
SASLE's
|
||||
RiceMail
|
||||
ATTMAIL
|
||||
MCImail
|
||||
vmd
|
||||
cso
|
||||
uiuc
|
||||
edu
|
||||
uiucvmd
|
||||
uiucvmd
|
||||
vmd
|
||||
cso
|
||||
uiuc
|
||||
edu
|
||||
Attmail
|
||||
vmd
|
||||
cso
|
||||
uiuc
|
||||
edu
|
||||
MCImail
|
||||
MCI
|
||||
MBX
|
||||
vmd
|
||||
cso
|
||||
uiuc
|
||||
edu
|
||||
mrcnext
|
||||
cso
|
||||
uiuc
|
||||
edu
|
||||
cd
|
||||
etext
|
||||
cd
|
||||
cd
|
||||
etext
|
||||
cd
|
||||
etext
|
||||
dir
|
||||
mget
|
||||
AAINDEX
|
||||
MGET
|
||||
ETEXTS
|
||||
etext
|
||||
etext
|
||||
ETEXT
|
||||
tm
|
||||
etext
|
||||
etext
|
||||
etext
|
||||
hysical
|
||||
TM
|
||||
ETEXTS
|
||||
tm
|
||||
etext
|
||||
tm
|
||||
etexts
|
||||
S
|
||||
etext
|
||||
etexts
|
||||
etexts
|
||||
etext
|
||||
etext
|
||||
etext
|
||||
tm
|
||||
etext
|
||||
dis
|
||||
NEGLI
|
||||
GENCE
|
||||
etext
|
||||
etext
|
||||
inaccu
|
||||
ETEXT
|
||||
ETEXT
|
||||
ETEXT
|
||||
etext
|
||||
pense
|
||||
etext
|
||||
ation
|
||||
etext
|
||||
distribu
|
||||
tion
|
||||
etext
|
||||
tm
|
||||
etext
|
||||
ically
|
||||
quires
|
||||
etext
|
||||
etext
|
||||
etext
|
||||
etext
|
||||
etext
|
||||
etext
|
||||
etext
|
||||
etext
|
||||
OCR
|
||||
etexts
|
||||
B
|
||||
ETEXTS
|
||||
Ver
|
||||
unperplexed
|
||||
confederacies
|
||||
proselytes
|
||||
Heresies
|
||||
invectives
|
||||
confederacies
|
||||
votaries
|
||||
PUBLIUS
|
||||
confederacies
|
||||
uncontradicted
|
||||
confederacies
|
||||
sovereignties
|
||||
widespreading
|
||||
sovereignties
|
||||
wellbalanced
|
||||
pursuaded
|
||||
pursuade
|
||||
confederacies
|
||||
confederacies
|
||||
PUBLIUS
|
||||
wellinformed
|
||||
confederacies
|
||||
confederacies
|
||||
violences
|
||||
borderers
|
||||
PUBLIUS
|
||||
confederacies
|
||||
uneasinesses
|
||||
confederacies
|
||||
embarrassments
|
||||
confederacies
|
||||
confederacies
|
||||
PUBLIUS
|
||||
animosities
|
||||
affection''
|
||||
confederacies
|
||||
confederacies
|
||||
confederacies
|
||||
confederacies
|
||||
confederacies
|
||||
borderers
|
||||
confederacies
|
||||
confederacies
|
||||
confederacies
|
||||
sovereignties
|
||||
PUBLIUS
|
||||
confederacies
|
||||
sovereignties
|
||||
rivalships
|
||||
SAMNIANS
|
||||
MEGARENSIANS
|
||||
V
|
||||
V
|
||||
descanted
|
||||
rivalships
|
||||
wellregulated
|
||||
antipathies
|
||||
PUBLIUS
|
||||
Plutarch's
|
||||
P
|
||||
Cambray
|
||||
Principes
|
||||
des
|
||||
Negociations''
|
||||
l'Abbe
|
||||
Mably
|
||||
ungranted
|
||||
cessions
|
||||
preponderated
|
||||
unpropitious
|
||||
SOVEREIGNTIES
|
||||
confederacies
|
||||
procrastinations
|
||||
resentments
|
||||
incumbrances
|
||||
delinquencies
|
||||
Delinquencies
|
||||
confederacies
|
||||
PUBLIUS
|
||||
retaken
|
||||
confederacies
|
||||
expedients
|
||||
confederacies
|
||||
confederacies
|
||||
oppressions
|
||||
encroachments
|
||||
menacings
|
||||
usurpations
|
||||
T
|
||||
disproportioned
|
||||
confederacies
|
||||
distempered
|
||||
PUBLIUS
|
||||
sophisms
|
||||
corruptions
|
||||
PUBLIUS
|
||||
Lawa
|
||||
wellconstructed
|
||||
mischiefs
|
||||
animosities
|
||||
mischiefs
|
||||
suffrages
|
||||
suffrages
|
||||
PUBLIUS
|
||||
rivalships
|
||||
intermeddlings
|
||||
concentred
|
||||
confederated
|
||||
fluctations
|
||||
unsalable
|
||||
PUBLIUS
|
||||
philosophiques
|
||||
Americains
|
||||
rivalship
|
||||
inperceptible
|
||||
confederacies
|
||||
confederacies
|
||||
embarrassments
|
||||
PUBLIUS
|
||||
confederacies
|
||||
sovereignties
|
||||
confederacies
|
||||
confederacies
|
||||
confederacies
|
||||
confederacies
|
||||
PUBLIUS
|
||||
concentred
|
||||
fellowcitizens
|
||||
PUBLIUS
|
||||
encroachments
|
||||
imperio
|
||||
contradistinguished
|
||||
mischiefs
|
||||
rivalships
|
||||
superintending
|
||||
improprieties
|
||||
sovereignties
|
||||
orbs
|
||||
intrusted
|
||||
delinquencies
|
||||
PUBLIUS
|
||||
confederacies
|
||||
suffrages
|
||||
delinquencies
|
||||
aggressing
|
||||
delinquencies
|
||||
instigations
|
||||
confederacies
|
||||
intrusted
|
||||
illhumors
|
||||
dismemberments
|
||||
PUBLIUS
|
||||
intrusted
|
||||
allurements
|
||||
transcendant
|
||||
unfrequently
|
||||
confederacies
|
||||
feudatories
|
||||
demesnes
|
||||
feudatories
|
||||
oppressions
|
||||
fiefs
|
||||
clanship
|
||||
encroachments
|
||||
rivalship
|
||||
PUBLIUS
|
||||
confederacies
|
||||
Amphictyonic
|
||||
aggressing
|
||||
Amphictyons
|
||||
Delphos
|
||||
Amphictyons
|
||||
Lacedaemonians
|
||||
Thebans
|
||||
Lacedaemonians
|
||||
Lacedaemonians
|
||||
orbs
|
||||
Milot
|
||||
hatreds
|
||||
dissentions
|
||||
Phocians
|
||||
Amphictyonic
|
||||
Phocians
|
||||
Thebans
|
||||
Amphictyons
|
||||
Amphictyonic
|
||||
praetors
|
||||
Philopoemen
|
||||
Achaeans
|
||||
Amphictyonic
|
||||
Aratus
|
||||
Mably
|
||||
Amphictyonic
|
||||
Achaeans
|
||||
Achaeans
|
||||
usurpers
|
||||
Peloponnesus
|
||||
Achaeans
|
||||
Cleomenes
|
||||
unprovoked
|
||||
Achaeans
|
||||
Achaeans
|
||||
Cleomenes
|
||||
intermeddling
|
||||
Cleomenes
|
||||
Achaeans
|
||||
tyrannies
|
||||
Achaeans
|
||||
AEtolians
|
||||
Achaeans
|
||||
Achaia
|
||||
PUBLIUS
|
||||
confederacies
|
||||
Gauls
|
||||
fiefs
|
||||
Suabian
|
||||
disturbers
|
||||
electorates
|
||||
inbecility
|
||||
defaulters
|
||||
Thuanus
|
||||
Donawerth
|
||||
Suabia
|
||||
Abb
|
||||
reannexed
|
||||
heriditary
|
||||
accomodating
|
||||
bailages
|
||||
Luzerne
|
||||
PUBLIUS
|
||||
Pfeffel
|
||||
Nouvel
|
||||
Abreg
|
||||
Chronol
|
||||
l'Hist
|
||||
d'Allemagne
|
||||
aristocracies
|
||||
superintends
|
||||
admiralties
|
||||
florins
|
||||
Belgic
|
||||
confedracy
|
||||
Mably
|
||||
contradistinguished
|
||||
PUBLIUS
|
||||
mulcts
|
||||
encroachments
|
||||
distempers
|
||||
usurpations
|
||||
King's
|
||||
PUBLIUS
|
||||
Jenkinson
|
||||
expedients
|
||||
reget
|
||||
Deleware
|
||||
confederated
|
||||
nonattendance
|
||||
mischiefs
|
||||
suffrages
|
||||
prevalency
|
||||
major's
|
||||
judicatories
|
||||
prepossessions
|
||||
infirmities
|
||||
PUBLIUS
|
||||
intrusted
|
||||
intrusted
|
||||
cavils
|
||||
confederacies
|
||||
indispensible
|
||||
PUBLIUS
|
||||
proprietory
|
||||
overflowings
|
||||
superadded
|
||||
expedients
|
||||
countenanced
|
||||
disconcertion
|
||||
encroachments
|
||||
PUBLIUS
|
||||
bils
|
||||
LEGISLATURE''
|
||||
rivalship
|
||||
perserverance
|
||||
Lacedaemonians
|
||||
PUBLIUS
|
||||
prevalency
|
||||
expedients
|
||||
wellinformed
|
||||
encroachments
|
||||
calamaties
|
||||
PUBLIUS
|
||||
inexplicitness
|
||||
expedients
|
||||
delinquencies
|
||||
PUBLIUS
|
||||
seditions
|
||||
scourges
|
||||
Confederacies
|
||||
Confederacies
|
||||
expedients
|
||||
usurpations
|
||||
intrusted
|
||||
usurpers
|
||||
usurpers
|
||||
usurpers
|
||||
usurpations
|
||||
PUBLIUS
|
||||
superintending
|
||||
COMITATUS
|
||||
COMITATUS
|
||||
intrusted
|
||||
COMITATUS
|
||||
Gorgons
|
||||
hydras
|
||||
chimeras
|
||||
dire''
|
||||
d'ors
|
||||
ducats
|
||||
intrenchments
|
||||
usurpers
|
||||
usurpations
|
||||
distempered
|
||||
superadded
|
||||
selfpreservation
|
||||
PUBLIUS
|
||||
bashaws
|
||||
fatuus
|
||||
embarrassments
|
||||
expedients
|
||||
usurers
|
||||
deficiences
|
||||
sightedness
|
||||
PUBLIUS
|
||||
DISQUISITIONS
|
||||
geometricians
|
||||
untractableness
|
||||
disingenuity
|
||||
superintending
|
||||
usurpations
|
||||
encroachments
|
||||
PUBLIUS
|
||||
resentments
|
||||
LEGISLATION''
|
||||
EXCISES''
|
||||
forbearances
|
||||
PUBLIUS
|
||||
ingrafted
|
||||
thereof''
|
||||
railings
|
||||
culumniated
|
||||
landtax
|
||||
reasoners
|
||||
intrusted
|
||||
PUBLIUS
|
||||
CENTURIATA
|
||||
TRIBUTA
|
||||
intrusted
|
||||
fifteenths
|
||||
twentieths
|
||||
PUBLIUS
|
||||
overstocked
|
||||
expedients
|
||||
acquirements
|
||||
rivalships
|
||||
suffrages
|
||||
expedients
|
||||
PUBLIUS
|
||||
rivalships
|
||||
bypaths
|
||||
monly
|
||||
taxations
|
||||
tyrannies
|
||||
expedients
|
||||
PUBLIUS
|
||||
rejudging
|
||||
confederacies
|
||||
rectifying
|
||||
intrusted
|
||||
naturalists
|
||||
infirmities
|
||||
animosities
|
||||
Zaleucus
|
||||
Locrians
|
||||
Numa
|
||||
Tullius
|
||||
Hostilius
|
||||
Tullius
|
||||
Hostilius
|
||||
Achaeus
|
||||
Aratus
|
||||
intrusted
|
||||
expedients
|
||||
selfpreservation
|
||||
protracting
|
||||
unpardonable
|
||||
impeachments
|
||||
impeachments
|
||||
overleaping
|
||||
PUBLIUS
|
||||
disquisitions
|
||||
oppressions
|
||||
PUBLIUS
|
||||
expositors
|
||||
ungranted
|
||||
pretermitting
|
||||
sixtieths
|
||||
PUBLIUS
|
||||
misthinking
|
||||
usurpations
|
||||
Confederacies
|
||||
animosities
|
||||
intrusted
|
||||
unvaried
|
||||
Confederacies
|
||||
PUBLIUS
|
||||
piracies
|
||||
felonies
|
||||
disembarrassed
|
||||
usurpations
|
||||
piracies
|
||||
felonies
|
||||
piracies
|
||||
felonies
|
||||
piracies
|
||||
felonies
|
||||
felonies
|
||||
upbraided
|
||||
oppressions
|
||||
emigrations
|
||||
secureties
|
||||
animosities
|
||||
superintending
|
||||
confederated
|
||||
mischiefs
|
||||
paupers
|
||||
superadding
|
||||
inhabitants''
|
||||
embarrassments
|
||||
interdicts
|
||||
PUBLIUS
|
||||
dockyards
|
||||
suffrages
|
||||
treasons
|
||||
wreaked
|
||||
superintending
|
||||
Amphictyons
|
||||
antirepublican
|
||||
confederacies
|
||||
superintending
|
||||
infirmities
|
||||
reciprocality
|
||||
PUBLIUS
|
||||
animosities
|
||||
mischiefs
|
||||
proper''
|
||||
EXPRESSLY''
|
||||
usurpers
|
||||
unredressed
|
||||
PUBLIUS
|
||||
Fournal
|
||||
unsacrificed
|
||||
confederacies
|
||||
encroachments
|
||||
rivalship
|
||||
encroachments
|
||||
countenancing
|
||||
PUBLIUS
|
||||
superintending
|
||||
prepossessions
|
||||
prepossessions
|
||||
prepossessions
|
||||
preorgatives
|
||||
defalcations
|
||||
encroachments
|
||||
embarrassments
|
||||
encroachments
|
||||
PUBLIUS
|
||||
selfappointed
|
||||
emphatical
|
||||
impeachments
|
||||
appointable
|
||||
impeachments
|
||||
impeachments
|
||||
appointable
|
||||
appointable
|
||||
PUBLIUS
|
||||
usurpations
|
||||
usurpations
|
||||
encroachments
|
||||
unfrequently
|
||||
encroachments
|
||||
p
|
||||
encroachments
|
||||
PUBLIUS
|
||||
Encroachments
|
||||
subjoined
|
||||
encroachments
|
||||
encroachments
|
||||
grantors
|
||||
bestows
|
||||
prepossessions
|
||||
numberous
|
||||
usurpations
|
||||
prepossessions
|
||||
PUBLIUS
|
||||
expedients
|
||||
PUBLIUS
|
||||
magistracies
|
||||
encroachments
|
||||
encroachments
|
||||
usurpations
|
||||
Confederacies
|
||||
oppressions
|
||||
PUBLIUS
|
||||
antiquaries
|
||||
usurpations
|
||||
PUBLIUS
|
||||
votaries
|
||||
t
|
||||
e
|
||||
regulatious
|
||||
acquirements
|
||||
reelections
|
||||
PUBLIUS
|
||||
confederacies
|
||||
PUBLIUS
|
||||
sixtyfive
|
||||
fellowcitizens
|
||||
allbe
|
||||
extravagancies
|
||||
PUBLIUS
|
||||
constitutents
|
||||
constitutents
|
||||
PUBLIUS
|
||||
Burgh's
|
||||
Disquisitions
|
||||
unpropitious
|
||||
suffrages
|
||||
PUBLIUS
|
||||
rivalship
|
||||
reapportionments
|
||||
reapportionments
|
||||
infirmities
|
||||
secessions
|
||||
PUBLIUS
|
||||
distempered
|
||||
intrusting
|
||||
rivalship
|
||||
confederacies
|
||||
PUBLIUS
|
||||
Ist
|
||||
Ist
|
||||
votaries
|
||||
primative
|
||||
importuned
|
||||
expedients
|
||||
PUBLIUS
|
||||
opposers
|
||||
suffrages
|
||||
suffrages
|
||||
unpardonable
|
||||
PUBLIUS
|
||||
V
|
||||
prepossessions
|
||||
mischiefs
|
||||
embarrassments
|
||||
impeachments
|
||||
indiscretions
|
||||
PUBLIUS
|
||||
unenlightened
|
||||
confederated
|
||||
Archons
|
||||
suffrages
|
||||
Ephori
|
||||
Cosmi
|
||||
usurpations
|
||||
encroachments
|
||||
Ephori
|
||||
usurpations
|
||||
PUBLIUS
|
||||
impeachments
|
||||
PUBLIUS
|
||||
impeachments
|
||||
impeachments
|
||||
animosities
|
||||
partialities
|
||||
inquisitors
|
||||
impeachments
|
||||
unawed
|
||||
impeachments
|
||||
impeachments
|
||||
impeachments
|
||||
disposers
|
||||
impeachments
|
||||
overbalanced
|
||||
impeachments
|
||||
impeachments
|
||||
reprobated
|
||||
PUBLIUS
|
||||
Impeachments
|
||||
impeachments
|
||||
wellestablished
|
||||
encroachments
|
||||
impeachments
|
||||
encroachments
|
||||
prevalency
|
||||
impeachments
|
||||
impeachments
|
||||
disquisitions
|
||||
impeachments
|
||||
counterpoises
|
||||
impeachments
|
||||
suffrages
|
||||
impeachments
|
||||
impeachments
|
||||
prostituted
|
||||
PUBLIUS
|
||||
Pennsylvanis
|
||||
impeachments
|
||||
inveighed
|
||||
mistresses
|
||||
voluptuousness
|
||||
visages
|
||||
janizaries
|
||||
disingenuity
|
||||
expedients
|
||||
applauses
|
||||
LAW''
|
||||
officers''
|
||||
session''
|
||||
years''
|
||||
palliated
|
||||
PUBLIUS
|
||||
V
|
||||
preestablished
|
||||
PUBLIUS
|
||||
Confederated
|
||||
crown's
|
||||
comfort''
|
||||
preferments
|
||||
PUBLIUS
|
||||
TAMONY
|
||||
Blackstone's
|
||||
p
|
||||
seditions
|
||||
repub
|
||||
lican
|
||||
intrusted
|
||||
votaries
|
||||
Achaeans
|
||||
Praetors
|
||||
mischiefs
|
||||
plebeians
|
||||
rivalships
|
||||
caprices
|
||||
jarrings
|
||||
anycounterbalancing
|
||||
weightiest
|
||||
scrunity
|
||||
mischiefs
|
||||
lic
|
||||
ONE''
|
||||
nattainable
|
||||
Decemvirs
|
||||
PUBLIUS
|
||||
Lolme
|
||||
seditions
|
||||
repub
|
||||
lican
|
||||
intrusted
|
||||
votaries
|
||||
Achaeans
|
||||
Praetors
|
||||
mischiefs
|
||||
plebeians
|
||||
rivalships
|
||||
caprices
|
||||
jarrings
|
||||
anycounterbalancing
|
||||
weightiest
|
||||
scrunity
|
||||
mischiefs
|
||||
lic
|
||||
ONE''
|
||||
nattainable
|
||||
Decemvirs
|
||||
PUBLIUS
|
||||
Lolme
|
||||
comports
|
||||
indued
|
||||
years'
|
||||
encroachments
|
||||
PUBLIUS
|
||||
expedients
|
||||
fellowcitizens
|
||||
readmission
|
||||
resentments
|
||||
suffrages
|
||||
overbalanced
|
||||
PUBLIUS
|
||||
largesses
|
||||
allurements
|
||||
selfdefense
|
||||
enaction
|
||||
missteps
|
||||
mischiefs
|
||||
opposers
|
||||
PUBLIUS
|
||||
seditions
|
||||
resentments
|
||||
welltimed
|
||||
PUBLIUS
|
||||
enaction
|
||||
years'
|
||||
intrusted
|
||||
intrusted
|
||||
PUBLIUS
|
||||
partialities
|
||||
antipathies
|
||||
animosities
|
||||
suffrages
|
||||
partialities
|
||||
antipathies
|
||||
animosities
|
||||
suffrages
|
||||
venalty
|
||||
venalty
|
||||
PUBLIUS
|
||||
uncomplying
|
||||
mischiefs
|
||||
embarrassments
|
||||
cavils
|
||||
PUBLIUS
|
||||
encroachments
|
||||
oppressions
|
||||
bulwarks
|
||||
encroachments
|
||||
oppressions
|
||||
mischiefs
|
||||
PUBLIUS
|
||||
Martin's
|
||||
impeachments
|
||||
PUBLIUS
|
||||
judicary
|
||||
unredressed
|
||||
bickerings
|
||||
animosities
|
||||
cognizances
|
||||
States''
|
||||
emited
|
||||
judicatories
|
||||
inconviences
|
||||
mischiefs
|
||||
wellinformed
|
||||
mischiefs
|
||||
PUBLIUS
|
||||
is''
|
||||
impeachments
|
||||
judical
|
||||
usurpations
|
||||
encroachments
|
||||
contraventions
|
||||
usurpations
|
||||
impeachments
|
||||
usurpations
|
||||
intrusted
|
||||
impeachments
|
||||
AUTHORUZE
|
||||
prevalency
|
||||
sovereignties
|
||||
inconveniencies
|
||||
PUBLIUS
|
||||
COURT''
|
||||
DICTIO
|
||||
juris
|
||||
dictio
|
||||
judicatories
|
||||
sovereignties
|
||||
T
|
||||
intrusted
|
||||
judicatories
|
||||
establish''
|
||||
PUBLIUS
|
||||
generals''
|
||||
oppressions
|
||||
impeachments
|
||||
intrusted
|
||||
heretofore''
|
||||
wellregulated
|
||||
litigations
|
||||
judicatories
|
||||
embarrassments
|
||||
unpardonable
|
||||
encroachments
|
||||
encroachments
|
||||
PUBLIUS
|
||||
opposers
|
||||
attainted
|
||||
Usays
|
||||
e
|
||||
emphatical
|
||||
abridgements
|
||||
preserved''
|
||||
intrusted
|
||||
overbalanced
|
||||
rivalship
|
||||
defaulters
|
||||
railings
|
||||
PUBLIUS
|
||||
Blackstone's
|
||||
p
|
||||
Blackstone's
|
||||
p
|
||||
asperities
|
||||
disputants
|
||||
concealments
|
||||
intemperances
|
||||
T
|
||||
encroachments
|
||||
Usays
|
||||
PUBLIUS
|
||||
Hume's
|
||||
Etext
|
||||
|
||||
WORDS MISSPELLED: 935
|
||||
WORDS IN DICTIONARY: 143091
|
||||
WORDS IN TEXT: 196784
|
||||