How to Reload, Refresh, Update, Webpack, Transpile, or `Whatever You Want to Call it` a React App on Glitch.com

This dev tip is brought to you by the developer of MoneyPhone: Personal Expense Tracking for Android and iOS. Consistently spend less than you earn each month and get your finances under control when you start monitoring your expenses with MoneyPhone!

Tonight I discovered this really cool quickstart tutorial on ReactJS from the team at Glitch.com where you can actually start programming in ReactJS in your browser using the Glitch.com web-based coding environment without having to use create-react-app or webpack to build your app. They handle all of the hosting and tooling for you. Pretty neat huh?

The only problem is hot reloading doesn’t always work. But after a little fiddling around I figured out a work around to get Glitch to sometimes hot reload everything when necessary: Simply go in and add a comment to the server.js file to trick glitch into hot reloading everything =>

// glitch reload!

If that doesn’t work, which it may not as I’ve found. You may just want to try using REPL.it instead to do your ReactJS coding practice in the browser using a web based coding environment. After playing around with REPL.it’s competing ReactJS browser based coding environment, I think it is probably a little bit better, albeit somewhat slower.

So there you have it. Maybe the best way to get started with React and Glitch is to watch their excellent 5 part video tutorial, but actually do your coding on REPL.it instead.

 

My Job Application to Plaid Inc.

Submitted a really interesting application to Plaid Inc. tonight… through their API! Pretty interesting huh? Originally I submitted an application via the startup social network AngelList, but happened to discover their “Apply by API” option while checking out their careers page. Wish me luck!

My Application & Server Response from the Plaid API:

# REFERENCE: GET and POST requests using Python
# https://www.geeksforgeeks.org/get-post-requests-using-python/
# REFERENCE: Post JSON using Python Requests
# https://bit.ly/2w6YHGa
import requests
import json
url = "https://contact.plaid.com/jobs"
data = {
'name': 'Christopher Pedersen',
'email': 'chris@topherpedersen.com',
'resume': 'https://bit.ly/ChristopherPedersensResume',
'github': 'https://www.linkedin.com/in/christopher-pedersen-a54a87b6/',
'twitter': '@topherPedersen',
'website': 'https://topherpedersen.blog',
'location': "Dallas, TX",
'favorite candy': 'Butterfinger',
'superpower': 'Wingsuit Pilot'
}
data = json.dumps(data)
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
http_post_request = requests.post(url=url, data=data, headers=headers)
server_response = http_post_request.text
print(server_response)
view raw job_application.py hosted with ❤ by GitHub
 

PhaserJS Starter Template

Phaser 3 Starter Template for use with my students @ theCoderSchool =>

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.19.0/phaser.js"></script>
<script src="game.js"></script>
</body>
</html>
view raw phaser.html hosted with ❤ by GitHub
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 200 }
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
function preload () {
}
function create () {
}
function update() {
}
view raw game.js hosted with ❤ by GitHub
 

CordovaError: Promise rejected with non-error: ‘xcode-select: error: tool \’xcodebuild\’ requires Xcode, but active developer directory \’/Library/Developer/CommandLineTools\’ is a command line tools instance\n’

This dev tip is brought to you by the developer of MoneyPhone: Personal Expense Tracking for Android and iOS. Consistently spend less than you earn each month and get your finances under control when you start monitoring your expenses with MoneyPhone!

Okay, so it looks like you’re having some trouble trying to run your Apache Cordova app on your iPhone. No worries! This blog post should get you pointed in the right direction.

First, if you happen to be receiving this CordovaError regarding xcode-select try installing this one dependency before attempting to run the app again on your device:

$ npm install -g ios-deploy

This is what the Official Cordova documentation suggests doing. However, this actually didn’t work for me for whatever reason. Luckily, I was able to install ios-deploy using brew instead, so maybe you should try that:

$ brew install ios-deploy

Now even though you should have all of the required dependencies installed (assuming your ran a traditional hello, world with swift and Xcode before installing Cordova), you may still find that you are running into the same error. The next step towards my eventual solution was running the following command to fix xcode-select:

$ sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

We’re getting closer. But I happened to next encounter an error message that read something like…

error: Signing for “HelloCordova” requires a development team. Select a development team in the Signing & Capabilities editor. (in target ‘HelloCordova’ from project ‘HelloCordova’)

The last step you need to take is to log in to developer.apple.com to figure out your developmentTeam identifier so you can set the developmentTeam flag when you go to run the app. This should fix the above error message. The developmentTeam identifier is located next to your name when you log in to developer.apple.com up in the top right hand corner of the website.

Last, run the app while remembering to set the necessary flags:

$ cordova run ios --device --developmentTeam="XX34TU9917" --automaticProvisioning=true

P.S. I made up the XX34TU9917 developmentTeam, so make sure you use your actual developmentTeam identifier found at developer.apple.com.

 

Apache Cordova Error: Failed to find ‘JAVA_HOME’ environment variable. Try setting it manually.

This dev tip is brought to you by the developer of MoneyPhone: Personal Expense Tracking for Android and iOS. Consistently spend less than you earn each month and get your finances under control when you start monitoring your expenses with MoneyPhone!

Hello there dear internet friend! It looks like you are having some trouble getting Apache Cordova to work. If you happen to be on a Mac, this blog post is for you! Likewise, a similar fix should work on Windows as well.

This isn’t my first time running into this quite annoying problem. Assuming you have Android Studio installed, the issue is either that Android Studio hasn’t set a global path to Java, or Android Studio is using a newer version of Java than the older version 8 that Cordova is still using.

Now if you happen to be really good with the UNIX operating system you can go track down Java and set the path yourself, or you can simply go with the easier solution that I’ve been using on all of my machines.

First, go ahead and install the brew package manager with the following terminal command:

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 

Next, install cask and the OpenJDK version of Java:

$ brew tap caskroom/cask

$ brew tap AdoptOpenJDK/openjdk

$ brew cask install adoptopenjdk8

Now, we still aren’t quite done. If you try to run cordova at this point you will likely encounter a similar error related to grade:

Checking Java JDK and Android SDK versions
ANDROID_SDK_ROOT=undefined (recommended setting)
ANDROID_HOME=/Users/topher/Library/Android/sdk (DEPRECATED)
Could not find an installed version of Gradle either in Android Studio,
or on your system to install the gradle wrapper. Please include gradle
in your path, or install Android Studio

To fix this, all you have left to do is install gradle with brew:

$ brew install gradle

And that’s it! Now you can run your Cordova app on your device:

$ cordova run android --device

 

UISceneSession is only available in iOS 13.0 or newer

This dev tip is brought to you by the developer of MoneyPhone: Personal Expense Tracking for Android and iOS. Consistently spend less than you earn each month and get your finances under control when you start monitoring your expenses with MoneyPhone!

Okay, so you’ve stumbled upon this terribly annoying error message: UISceneSession is only available in iOS 13.0 or newer, now what? The best answer is to simply update the software on the iPhone that you are trying to run your app.

The worse answer is to actually go in to the code by hand and add @available attributes to the parts of the boilerplate code generated by Xcode that aren’t compatible with the older version of iOS running on your test device. But in my opinion this is trying to swim against the current. Just go ahead and update the software on your phone and all will be well.

Although if I remember correctly, this is always going to be sort of a damned-if-you-update, damned-if-you-don’t-update sort of situation. You may end up finding yourself running into the opposite situation: You update the version of iOS on your iPhone, then the older version of Xcode becomes out of sync with your device. Unfortunately this is just the way of native mobile development— a never ending series of software updates.

 

How to Teach Turtle Graphics with Python

Quick little starter template for use teaching introductory python programming to students using the turtle graphics library =>

import turtle
screen = turtle.Screen()
screen.screensize()
screen.setup(width=1.0, height=1.0)
screen.addshape("sprite.gif")
sprite = turtle.Turtle()
sprite.shape("sprite.gif")
sprite.penup()
sprite.goto(0, 0)
sprite.goto(200, 200)
sprite.goto(-200, 200)
sprite.goto(-200, -200)
sprite.goto(200, -200)
sprite.goto(200, 200)
turtle.mainloop()
 

woohoo.cs

Funny C# Winforms project/tutorial I built with one of my students. Inspired by woohooooo.com. Executable version coming soon…

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WoohooWinform
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Find File Path to Main Directory (Contains Main Program and Additional Files)
string pathToDirectory = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
// Create SoundPlayer Object Which Will Play Our WAV File
System.Media.SoundPlayer player = new System.Media.SoundPlayer();
// Tell The SoundPlayer Object Where Our WAV File is Located
player.SoundLocation = pathToDirectory + @"\woohoo.wav";
// Say Woohoo!
player.Play();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
view raw woohoo.cs hosted with ❤ by GitHub
 

Cordova Screen Orientation (Lock) Plugin Not Working

This dev tip is brought to you by the developer of MoneyPhone: Personal Expense Tracking for Android and iOS. Consistently spend less than you earn each month and get your finances under control when you start monitoring your expenses with MoneyPhone!

If you find yourself struggling to get the Apache Cordova screen orientation lock plugin to work, the problem is most likely that you are calling the .lock() method before the ‘deviceready’ event has fired. To fix this problem, simply create a call back function containing your .lock() method call, then pass this callback function as an argument to the deviceready event listener like so =>

First, make sure to install the screen orientation plugin for apache cordova

$ cordova plugin add cordova-plugin-screen-orientation

Then, rewrite your code to look something like this…

// Lock Device Orientation
function lockDeviceOrientationCallback() {
// set to either landscape
screen.orientation.lock('portrait');
console.log("locking device orientation...");
}
document.addEventListener("deviceready", lockDeviceOrientationCallback, false);
 

Pong in Python vs. Pong in JavaScript: Battle of Introductory Game Dev Tutorials

Battle of the introductory game dev tutorials by myself and my student “Squitato” =>

# Copyright (c) 2018 Peter Kwak (Edited by Chris Pedersen)
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
import turtle
# Create Game Window
screen = turtle.Screen()
# screen.setup(500, 400)
screen.screensize(500, 500, "black")
screen.bgcolor("black")
# screen.addshape("Paddle.jpg")
# Create Ping Pong Ball
ball = turtle.Turtle()
ball.penup()
ball.speed(0)
ball.shape("circle")
ball.color("white")
# Create Left Ping Pong Paddle
paddle1 = turtle.Turtle()
paddle1.penup()
paddle1.speed(0)
paddle1.setx(-200)
paddle1.shape("square")
paddle1.shapesize(4.5, 1, 0)
paddle1.fillcolor("white")
# Create Right Ping Pong Paddle
paddle2 = turtle.Turtle()
paddle2.penup()
paddle2.speed(0)
paddle2.setx(200)
paddle2.shape("square")
paddle2.shapesize(4.5, 1, 0)
paddle2.fillcolor("white")
# Create Scoreboard
scoreWriter = turtle.Turtle()
scoreWriter.penup()
scoreWriter.speed(0)
scoreWriter.hideturtle()
scoreWriter.color("white")
# Set Ball Trajectory
rise = 3
run = 3
# Set Score
score1 = 0
score2 = 0
# Create Function Which Will Move Player 1's Paddle Up
def up1():
paddle1.sety(paddle1.ycor() + 50)
# Create Function Which Will Move Player 1's Paddle Down
def down1():
paddle1.sety(paddle1.ycor() - 50)
# Create Function Which Will Move Player 2's Paddle Up
def up2():
paddle2.sety(paddle2.ycor() + 50)
# Create Function Which Will Move Player 2's Paddle Down
def down2():
paddle2.sety(paddle2.ycor() - 50)
# Create Function To Update Scoreboard
def updateScoreboard():
global scoreWriter
global score1
global score2
global ball
scoreWriter.clear()
myFont = ("Arial", 40, "bold")
scoreWriter.goto(-100, 150)
scoreWriter.write(score1, font=myFont)
scoreWriter.goto(100, 150)
scoreWriter.write(score2, font=myFont)
ball.goto(0, 0)
# Set Event Listeners
# These event listeners will listen for button presses (up, down, etc.)
screen.onkey(up1, "w")
screen.onkey(down1, "s")
screen.onkey(up2, "Up")
screen.onkey(down2, "Down")
screen.listen()
# Create Main Game Loop (Simulates Time, Keeps Game Running)
while True:
# Move Ball
ball.goto(ball.xcor() + run, ball.ycor() + rise)
# Detect Top or Bottom Boundary Strike
# (Reverses the Ball's Direction of Travel)
if ball.ycor() > 200 or ball.ycor() < -200:
rise = -rise
# Detect Paddle Strike (Player 1)
# (Also Reverses the Ball's Direction of Travel)
if abs(paddle1.xcor() - ball.xcor()) < 15:
if abs(paddle1.ycor() - ball.ycor()) < 50:
run = -run
# Detect Paddle Strike (Player 2)
# (Also Reverses the Ball's Direction of Travel)
if abs(paddle2.xcor() - ball.xcor()) < 15:
if abs(paddle2.ycor() - ball.ycor()) < 50:
run = -run
# Detect When A Player Scores a Point
if ball.xcor() > 250:
# Increment player1's score by 1 point when his ball
# travels past the paddle of his opponent, player 2.
score1 = score1 + 1
updateScoreboard()
ball.goto(0, 0)
elif ball.xcor() < -250:
# Increment player2's score by 1 point when his ball
# travels past the paddle of his opponent, player 1.
score2 = score2 + 1
updateScoreboard()
ball.goto(0, 0)
# Christine, My Super Sweet AI Goes HERE...
if ball.ycor() > paddle2.ycor() + 25:
paddle2.sety(paddle2.ycor() + 15)
elif ball.ycor() < paddle2.ycor() - 25:
paddle2.sety(paddle2.ycor() - 15)
view raw pong.py hosted with ❤ by GitHub

NOTE: For the PongJS demo, you will need to manually install p5.play.js as it is not available via CDN =>

<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
<!-- NOTE: Must Download and Install p5.play.js Manually, it is not available via CDN -->
<script src="p5.play.js"></script>
</head>
<body>
<script src="pong.js"></script>
</body>
</html>
view raw pong.html hosted with ❤ by GitHub
//pong clone
//mouse to control both paddles
var paddleA, paddleB, ball, wallTop, wallBottom;
var MAX_SPEED = 10;
function setup() {
createCanvas(800, 400);
//frameRate(6);
paddleA = createSprite(30, height/2, 10, 100);
paddleA.immovable = true;
paddleB = createSprite(width-28, height/2, 10, 100);
paddleB.immovable = true;
wallTop = createSprite(width/2, -30/2, width, 30);
wallTop.immovable = true;
wallBottom = createSprite(width/2, height+30/2, width, 30);
wallBottom.immovable = true;
ball = createSprite(width/2, height/2, 10, 10);
ball.maxSpeed = MAX_SPEED;
paddleA.shapeColor = paddleB.shapeColor =ball.shapeColor = color(255, 255, 255);
ball.setSpeed(MAX_SPEED, -180);
}
function draw() {
background(0);
paddleA.position.y = constrain(mouseY, paddleA.height/2, height-paddleA.height/2);
paddleB.position.y = constrain(mouseY, paddleA.height/2, height-paddleA.height/2);
ball.bounce(wallTop);
ball.bounce(wallBottom);
var swing;
if(ball.bounce(paddleA)) {
swing = (ball.position.y-paddleA.position.y)/3;
ball.setSpeed(MAX_SPEED, ball.getDirection()+swing);
}
if(ball.bounce(paddleB)) {
swing = (ball.position.y-paddleB.position.y)/3;
ball.setSpeed(MAX_SPEED, ball.getDirection()-swing);
}
if(ball.position.x<0) {
ball.position.x = width/2;
ball.position.y = height/2;
ball.setSpeed(MAX_SPEED, 0);
}
if(ball.position.x>width) {
ball.position.x = width/2;
ball.position.y = height/2;
ball.setSpeed(MAX_SPEED, 180);
}
drawSprites();
}
view raw pong.js hosted with ❤ by GitHub