A Mix of Entertainment & Education

Almost everything I do I try to have a mix of entertainment and education. There’s a sweet spot between those… If it’s too entertaining you don’t learn anything, and if it’s too educational nobody listens.

Russ Roberts
 

How to Build a RESTful API in Python with Flask in 50 Lines or Less

Really simple example of how to build an API with Python and Flask that listens for HTTP requests and spits out JSON. The hard part of all of this is building the JSON with python. For really simple JSON we can just use a dictionary. However, where things get complicated is if you want your JSON objects to contain objects. The work around I’ve found is to simply create a dictionary of dictionaries, where we will use dictionaries instead of objects. In the example below first_category, second_category, and third_category would normally be represented as objects, but have been converted to dictionaries instead:

# Import Flask
from flask import Flask, render_template, request, jsonify, session, redirect, url_for, Response
app = Flask(__name__)
# REFERENCE: http://blog.luisrei.com/articles/flaskrest.html
@app.route('/dictionary-to-json-test', methods=['GET', 'POST'])
def dictionary_to_json_test():
list_of_categories = []
first_category = {
"name": "Fast Food",
"number_of_transactions": 13,
"amount_spent": 427.33
}
second_category = {
"name": "Restaurants",
"number_of_transactions": 1,
"amount_spent": 54.0
}
third_category = {
"name": "Entertainment",
"number_of_transactions": 2,
"amount_spent": 125.0
}
list_of_categories.append(first_category)
list_of_categories.append(second_category)
list_of_categories.append(third_category)
dictionary_of_dictionaries = {
"category": list_of_categories
}
# Convert Dictionary to JSON
json_obj = json.dumps(dictionary_of_dictionaries)
# Create Response Object
response_obj = Response(json_obj, status=200, mimetype='application/json')
# Return JSON (Response Object)
return response_obj
if __name__ == "__main__":
app.run()
 

MoneyPhone Feature Requests and Bug Tracking

Hello Internet Friends,

This post isn’t really for you. I just wanted to jot down a few notes on feature requests and bugs that need to be addressed with my app MoneyPhone before I forget:

Feature Requests

  1. Allow users to edit transactions
  2. Add spending categories
  3. Include pending payments (accurately)
  4. Bring back “money spent yesterday” sms feature
  5. Add category budgets

Bug Tracking

  1. Figure out how to handle expired access_tokens

 

Get Year Month & Day as Integers from an ISO 8601 Date String in Python

date_str = "2017-01-29"
year_str = date_str[0] + date_str[1] + date_str[2] + date_str[3]
month_str = date_str[5] + date_str[6]
day_str = date_str[8] + date_str[9]
year_int = int(year_str)
month_int = int(month_str)
day_int = int(day_str)
print(year_int)
print(month_int)
print(day_int)
 

The Beautiful Thing About Programming & Startups

 

Free Marketing on Quora— a Traction Channel Experiment

Dear Internet Friends,

Tonight I wanted to write a real quick post on an experiment I’m conducting. I’m still struggling to find a traction channel for promoting my personal finance app, MoneyPhone, so on a whim I decided maybe I should try answering some questions regarding the topic of personal finance on Quora. To my surprise the site actually has a pretty decent Personal Finance / Budgeting section with many recent unanswered questions on the topic. And since I’m actually using MoneyPhone successfully to solve my own personal finance and budgeting problems, I decided to answer a couple of questions suggesting the OPs try my app. Not sure if my answers will get any views, or result in any downloads, but it’s worth a shot right?

So without further ado, here are the links to my two answers:

Read topherPedersen's answer to How do you avoid spending the next month’s budget this month? on Quora Read topherPedersen's answer to How do I create a monthly budget? on Quora

Sincerely,

Your Friend Topher

UPDATE (8/3/2019): I woke up the day after posting my two Quora answers and found that Quora moderators had deleted one of my answers. I sort of assumed that this would be a possibility considering they need to make money from people looking to market/advertise on their platform. However, I don’t think its a very good policy as I was ready to start spending money on their platform to promote some answers but have now changed my mind. Really, it was quite unnecessary. They easily could just push answers from marketers down the page unless they pay to push their answers up to the top. O well! On to the next traction channel.

 

Get Fired Up Like Jorge Masvidal

Feeling fired up, like Jorge Masvidal.

 

SpaceWalk PhaserJS Tutorial

Cool “spacewalk” PhaserJS tutorial for use with my students @ theCoderSchool:

Repl.it Starter Template (Includes Game Assets, No Code)

<!DOCTYPE html>
<html>
<head>
<script src="//cdn.jsdelivr.net/npm/phaser@3.18.0/dist/phaser.js"></script>
<!-- import phaser (phaser.js) -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/phaser-ce/2.13.2/phaser.min.js"></script> -->
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script>
var config = {
type: Phaser.AUTO,
width: window.outerWidth,
height: window.innerHeight,
physics: {
default: 'arcade',
arcade: {
/* gravity: { y: 300 }, */
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
// DECLARE GLOBAL VARIABLES
var spaceMan;
var game = new Phaser.Game(config);
function preload() {
// do stuff
this.load.image('space', 'assets/high-res-space.jpg');
// LOAD SPRITE
this.load.image('spaceMan', 'assets/spaceMan.png');
}
function create() {
// do stuff
this.add.image(window.outerWidth / 2, window.innerHeight / 2, 'space');
spaceMan = this.physics.add.sprite(window.outerWidth / 2, window.innerHeight / 2, 'spaceMan');
spaceMan.angle = 270;
// ADD CURSORS (USER INPUT / CONTROLS)
cursors = this.input.keyboard.createCursorKeys();
// SET SPACEMAN VELOCITY
spaceMan.body.velocity.x = 0;
spaceMan.body.velocity.y = 0;
spaceMan.body.angularVelocity = 0;
spaceMan.body.velocityFromAngle = 0;
spaceMan.setDamping(true);
spaceMan.setDrag(0.99);
spaceMan.setMaxVelocity(200);
}
var coordinatesDisplayed = false;
var centerX;
var centerY;
function update() {
// ROTATIONAL THRUST
if (cursors.left.isDown) {
spaceMan.angle -= 0.5;
} else if (cursors.right.isDown) {
spaceMan.angle += 0.5;
}
// FORWARD THRUST
if (cursors.up.isDown) {
this.physics.velocityFromRotation(spaceMan.rotation, 200, spaceMan.body.acceleration);
// DOWNWARD THRUST
} else if (cursors.down.isDown) {
this.physics.velocityFromRotation(spaceMan.rotation, -200, spaceMan.body.acceleration);
} else {
spaceMan.setAcceleration(0);
}
this.physics.world.wrap(spaceMan, 250);
}
</script>
</body>
</html>
view raw spacewalk.html hosted with ❤ by GitHub
 

Ratchet: Swapping Out Push.js for Turbolinks

Quick update on my latest HTML5/Apache-Cordova application. I recently decided to ditch the Materialize CSS framework in favor of Ratchet, an HTML5 framework from one of the core contributors to Bootstrap. However, I’ve run into a bunch of problems using the Push.js library that comes with Ratchet. Push.js is kind of like Turbolinks in that it is meant to make building single page HTML5 applications a lot simpler than using something like React, Angular, or Vue. However push.js isn’t very well documented and I haven’t been able to get it to do what I want!

So… since I’ve already figured out how to get Turbolinks to do what I want, I’ve decided that I’m just going to dump the Push.js library that comes bundled with Ratchet in favor of Turbolinks instead. While I still don’t have everything worked out completely, I think Ratchet + Turbolinks is going to be the easiest way for me to build an HTML5 application using Apache Cordova. And hey, when I get all of this finished maybe I can just combine Ratchet and Turbolinks into my own nifty HTML5 framework? I really like Ratchet so far, it just seems to be missing some stuff when it comes to developing single page applications. To build my app the “push.js” way I believe would require me to do a lot of server-side rendering which isn’t really something I want to do.

I know that there are obviously the big three SPA frameworks out there that solve this problem, but they are a lot more complicated that what I want. I wonder if I can use Ratchet and Turbolinks plus a little of my own ingenuity to make the simplest single page application framework? I really want something that is almost as easy as just creating a website with straight HTML. I know it won’t end up being quite that simple, but I think I could whip up something like this, where when a user clicks on a button/link we =>

  1. Fetch some data from a server with AJAX (if necessary)
  2. Load new HTML that is stored locally on the phone with Turbolinks
  3. Add some JavaScript to each new HTML page that will dynamically update our HTML using the data returned from the server.
 

FlappyBird Programming Tutorial with JavaScript and Phaser 3

Quick little FlappyBird tutorial written in JavaScript using the Phaser 3 HTML5 Game Framework. See the starter template on Repl.it for the game assets. Code by Sanay N., a rockstar coding student @ theCoderSchool in Flower Mound, TX and his instructor Topher P. =>

STARTER TEMPLATE: https://repl.it/@topherPedersen/FlappyBirdJS-STARTER-TEMPLATE

<!doctype html>
<!-- FlappyBirdJS by Sanay N. & Topher P.-->
<!-- https://github.com/topherPedersen/FlappyBirdJS -->
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Making your first Phaser 3 Game - Part 2</title>
<script src="//cdn.jsdelivr.net/npm/phaser@3.11.0/dist/phaser.js"></script>
<style type="text/css">
body {
margin: 0;
}
#title-div {
width: 600px;
overflow: hidden;
text-align: center;
}
</style>
</head>
<body>
<div id="title-div">
<p><strong>FlappyBirdJS by Sanay N., a Rockstar Coding Student @ theCoderSchool</strong></p>
</div>
<script type="text/javascript">
/**
** FlappyBirdJS by Sanay (a Rockstar Coding Student @ theCoderSchool)
** with a little help from his instructor topherPedersen
**/
// REFERENCE (Official Phaser Tutorial Source Code): https://github.com/topherPedersen/OfficialPhaser3Tutorial
var config = {
type: Phaser.AUTO,
width: 600,
height: 400,
physics: {
default: 'arcade',
arcade: {
gravity: {y: 300},
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
// Game Variables
var bird;
var cursors;
var bottom_pipe = [];
var top_pipe = [];
var gameOver = false;
var endGame;
var distance;
initialYAxisOffset = [];
function preload () {
this.load.image('sky', 'assets/sky.png');
this.load.image('bird', 'assets/bird.png');
this.load.image('pipe', 'assets/pipe.png');
}
function create () {
// Add Sky
this.add.image(400, 300, 'sky');
// Add Flappy Bird
bird = this.physics.add.sprite(20, 40, 'bird');
// Add Collision Detection
bird.setBounce(0.2);
bird.setCollideWorldBounds(true);
bird.body.setGravityY(300);
// TODO: Sanay, use a for-loop to create three pipes.
// Reference the "Add Flappy Bird" for how to add a sprite
var xPos = 0;
var firstRandomNumber;
for (var i = 0; i < 3; i++) {
firstRandomNumber = (Math.floor(Math.random() * 10)) + 1;
if (firstRandomNumber < 6) {
// add random positive number to pipe's new y position
initialYAxisOffset[i] = (Math.floor(Math.random() * 10)) * 10;
} else {
// add random negative number to pipe's new y position
initialYAxisOffset[i] = (Math.floor(Math.random() * 10)) * (-10);
}
}
var offset;
// Create Top Pipes
for (var i = 0; i < 3; i++) {
offset = initialYAxisOffset[i];
top_pipe[i] = this.physics.add.sprite(550 + xPos, -50 + offset, 'pipe');
top_pipe[i].body.setAllowGravity(false);
top_pipe[i].body.setVelocityX(-150);
top_pipe[i].inableBody = true;
top_pipe[i].immovable = true;
top_pipe[i].flipY = true;
// Adjust Physics for Pipe(s)
// pipe[i].setBounce(0.2);
// pipe[i].setCollideWorldBounds(true);
// pipe[i].body.setGravityY(0);
// this.physics.add.collider(pipe[i]);
xPos += 400;
}
// Create Bottom Pipes
xPos = 0; // reset xPos back to zero
for (var i = 0; i < 3; i++) {
offset = initialYAxisOffset[i];
bottom_pipe[i] = this.physics.add.sprite(550 + xPos, 450 + offset, 'pipe');
bottom_pipe[i].body.setAllowGravity(false);
bottom_pipe[i].body.setVelocityX(-150);
bottom_pipe[i].inableBody = true;
bottom_pipe[i].immovable = true;
// bottom_pipe[i].flipY = true;
// Adjust Physics for Pipe(s)
// pipe[i].setBounce(0.2);
// pipe[i].setCollideWorldBounds(true);
// pipe[i].body.setGravityY(0);
// this.physics.add.collider(pipe[i]);
xPos += 400;
}
onScreenText = this.add.text(212, 185, '', {fontSize: '32px', fill: '#00000' });
cursors = this.input.keyboard.createCursorKeys();
// Add Collision Detection Between Bird & Pipe(s)
this.physics.add.collider(bird, bottom_pipe, collisionCallback);
this.physics.add.collider(bird, top_pipe, collisionCallback);
}
var xPos = 0;
// Main Game Loop
function update () {
if (gameOver) {
bird.body.setGravityY(0);
for (var i = 0; i < 3; i++) {
bottom_pipe[i].body.setAllowGravity(false);
bottom_pipe[i].body.setVelocityX(0);
top_pipe[i].body.setAllowGravity(false);
top_pipe[i].body.setVelocityX(0);
}
return;
} else {
if (cursors.space.isDown) {
bird.setVelocityY(-250);
console.log('Space Bar is pressed, I am amazing')
}
// TODO: Sanay, write some code here in the main game loop
// to check to see if any of the pipes have gone off screen.
// -300
for (var i = 0; i < 3; i++) {
var firstRandomNumber = (Math.floor(Math.random() * 10)) + 1;
if (firstRandomNumber < 6) {
// add random positive number to pipe's new y position
var yAxisOffset = (Math.floor(Math.random() * 10)) * 10;
} else {
// add random negative number to pipe's new y position
var yAxisOffset = (Math.floor(Math.random() * 10)) * (-10);
}
if (bottom_pipe[i].body.x < -400) {
bottom_pipe[i].x = 850;
bottom_pipe[i].y = 450 + yAxisOffset;
}
if (top_pipe[i].body.x < -400) {
top_pipe[i].x = 850;
top_pipe[i].y = -50 + yAxisOffset;
}
}
}
}
function collisionCallback() {
gameOver = true;
// endGame.setText('Game Over');
bird.body.enable = false;
top_pipe[0].body.enable = false;
top_pipe[1].body.enable = false;
top_pipe[2].body.enable = false;
bottom_pipe[0].body.enable = false;
bottom_pipe[1].body.enable = false;
bottom_pipe[2].body.enable = false;
onScreenText.setText('GAME OVER');
}
</script>
</body>
</html>
view raw flappybird.html hosted with ❤ by GitHub