diff --git a/.devcontainer/DOCKERFILE b/.devcontainer/DOCKERFILE new file mode 100644 index 00000000..1d2bea26 --- /dev/null +++ b/.devcontainer/DOCKERFILE @@ -0,0 +1,24 @@ +ARG VARIANT=11 +FROM mcr.microsoft.com/vscode/devcontainers/java:${VARIANT} + +ARG INSTALL_ZSH="true" +ARG UPGRADE_PACKAGES="false" +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +COPY library-scripts/*.sh /tmp/library-scripts/ +RUN apt-get update \ + && /bin/bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \ + && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts + +COPY library-scripts/desktop-lite-debian.sh /tmp/library-scripts/ +RUN apt-get update && \ + export DEBIAN_FRONTEND=noninteractive && \ + bash /tmp/library-scripts/desktop-lite-debian.sh + +ENV DBUS_SESSION_BUS_ADDRESS="autolaunch:" DISPLAY=":1" LANG="en_US.UTF-8" LANGUAGE="en_US.UTF-8" +ENTRYPOINT ["/usr/local/share/desktop-init.sh"] +CMD ["sleep", "infinity"] + +#RUN if [ ! -d "/docker-java-home" ]; then ln -s "${JAVA_HOME}" /docker-java-home; fi diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..b2d46efb --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +{ + "name": "Java", + "build": { + "dockerfile": "DOCKERFILE", + "args": { + "VARIANT": "11", + "INSTALL_MAVEN": "false", + } + }, + + "settings": { + "terminal.integrated.shell.linux": "/bin/bash", + "java.home": "/docker-java-home" + }, + + "extensions": [ + "vscjava.vscode-java-pack" + ], + + "runArgs": ["--init", "--security-opt", "seccomp=unconfined"], + "forwardPorts": [6080], + "overrideCommand": false, + + "postCreateCommand": "java -version", + +} diff --git a/.devcontainer/library-scripts/common-debian.sh b/.devcontainer/library-scripts/common-debian.sh new file mode 100644 index 00000000..3ff81d32 --- /dev/null +++ b/.devcontainer/library-scripts/common-debian.sh @@ -0,0 +1,167 @@ +INSTALL_ZSH=${1:-"true"} +USERNAME=${2:-"vscode"} +USER_UID=${3:-1000} +USER_GID=${4:-1000} +UPGRADE_PACKAGES=${5:-"true"} + +set -e + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +if [ "${USERNAME}" = "none" ] || [ "${USERNAME}" = "root" ]; then + USERNAME=root + USER_UID=0 + USER_GID=0 +fi + +MARKER_FILE="/usr/local/etc/vscode-dev-containers/common" +if [ -f "${MARKER_FILE}" ]; then + echo "Marker file found:" + cat "${MARKER_FILE}" + source "${MARKER_FILE}" +fi + +export DEBIAN_FRONTEND=noninteractive + +apt-get-update-if-needed() +{ + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + echo "Running apt-get update..." + apt-get update + else + echo "Skipping apt-get update." + fi +} + +if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then + apt-get-update-if-needed + + PACKAGE_LIST="apt-utils \ + git \ + openssh-client \ + gnupg2 \ + iproute2 \ + procps \ + lsof \ + htop \ + net-tools \ + psmisc \ + curl \ + wget \ + rsync \ + ca-certificates \ + unzip \ + zip \ + nano \ + vim-tiny \ + less \ + jq \ + lsb-release \ + apt-transport-https \ + dialog \ + libc6 \ + libgcc1 \ + libgssapi-krb5-2 \ + libicu[0-9][0-9] \ + liblttng-ust0 \ + libstdc++6 \ + zlib1g \ + locales \ + sudo \ + ncdu \ + man-db" + + if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then + PACKAGE_LIST="${PACKAGE_LIST} libssl1.1" + fi + + LIBSSL=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '') + if [ "$(echo "$LIBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then + if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then + # Debian 9 + PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.2" + elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then + # Ubuntu 18.04, 16.04, earlier + PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.0" + fi + fi + + echo "Packages to verify are installed: ${PACKAGE_LIST}" + apt-get -y install --no-install-recommends ${PACKAGE_LIST} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 ) + + PACKAGES_ALREADY_INSTALLED="true" +fi + +if [ "${UPGRADE_PACKAGES}" = "true" ]; then + apt-get-update-if-needed + apt-get -y upgrade --no-install-recommends + apt-get autoremove -y +fi + +if [ "${LOCALE_ALREADY_SET}" != "true" ]; then + echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen + locale-gen + LOCALE_ALREADY_SET="true" +fi + +if id -u $USERNAME > /dev/null 2>&1; then + if [ "$USER_GID" != "$(id -G $USERNAME)" ]; then + groupmod --gid $USER_GID $USERNAME + usermod --gid $USER_GID $USERNAME + fi + if [ "$USER_UID" != "$(id -u $USERNAME)" ]; then + usermod --uid $USER_UID $USERNAME + fi +else + groupadd --gid $USER_GID $USERNAME + useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME +fi + +if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then + echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME + chmod 0440 /etc/sudoers.d/$USERNAME + EXISTING_NON_ROOT_USER="${USERNAME}" +fi + +RC_SNIPPET="$(cat << EOF +export USER=\$(whoami) +export PATH=\$PATH:\$HOME/.local/bin +if [[ \$(which code-insiders 2>&1) && ! \$(which code 2>&1) ]]; then + alias code=code-insiders +fi +EOF +)" + +if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then + echo "${RC_SNIPPET}" >> /etc/bash.bashrc + RC_SNIPPET_ALREADY_ADDED="true" +fi + +if [ "${INSTALL_ZSH}" = "true" ] && [ ! -d "/root/.oh-my-zsh" ] && [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then + apt-get-update-if-needed + apt-get install -y zsh + curl -fsSLo- https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash 2>&1 + echo "${RC_SNIPPET}" >> /etc/zsh/zshrc + echo -e "DEFAULT_USER=\$USER\nprompt_context(){}" >> /root/.zshrc + cp -fR /root/.oh-my-zsh /etc/skel + cp -f /root/.zshrc /etc/skel + sed -i -e "s/\/root\/.oh-my-zsh/\/home\/\$(whoami)\/.oh-my-zsh/g" /etc/skel/.zshrc + if [ "${USERNAME}" != "root" ]; then + cp -fR /etc/skel/.oh-my-zsh /etc/skel/.zshrc /home/$USERNAME + chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc + fi + ZSH_ALREADY_INSTALLED="true" +fi + +mkdir -p "$(dirname "${MARKER_FILE}")" +echo -e "\ + PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\ + LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\ + EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\ + RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\ + ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}" + +echo "Done!" diff --git a/.devcontainer/library-scripts/desktop-lite-debian.sh b/.devcontainer/library-scripts/desktop-lite-debian.sh new file mode 100644 index 00000000..03a64139 --- /dev/null +++ b/.devcontainer/library-scripts/desktop-lite-debian.sh @@ -0,0 +1,347 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +# Syntax: ./desktop-lite-debian.sh [non-root user] [vnc password] [install no vnc flag] +# +# Usage: +# +# 1. Add this file to .devcontainer/library-scripts +# +# 2. Add the following to your .devcontainer/Dockerfile: +# +# COPY library-scripts/desktop-lite-debian.sh /tmp/library-scripts/ +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && bash /tmp/library-scripts/desktop-lite-debian.sh +# ENV DBUS_SESSION_BUS_ADDRESS="autolaunch:" DISPLAY=":1" LANG="en_US.UTF-8" LANGUAGE="en_US.UTF-8" +# ENTRYPOINT ["/usr/local/share/desktop-init.sh"] +# CMD ["sleep", "infinity"] +# +# The ENTRYPOINT script can be chained with another script by adding it to the array after desktop-init.sh. +# If you need to select a different locale, be sure to add it to /etc/locale.gen and run locale-gen. +# +# 3. And the following to devcontainer.json: +# +# "runArgs": ["--init", "--security-opt", "seccomp=unconfined"], +# "forwardPorts": [6080, 5901], +# "overrideCommand": false +# +# 4. You'll be able to use a web based desktop viewer on port **6080** or connect a VNC viewer to port **5901**. +# +# 5. Default **password**: vscode +# +# The window manager is Fluxbox (http://fluxbox.org/). **Right-click** to see the application menu. If you need +# a browser, you can install Firefox ESR by adding the following to your Dockerfile: +# +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && apt-get install -y firefox-esr +# +# If you want the full version of Google Chrome in the desktop: +# +# 1. Add the following to your Dockerfile instead: +# +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && curl -sSL https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /tmp/chrome.deb \ +# && apt-get -y install /tmp/chrome.deb \ +# && rm -rf /tmp/chrome.deb +# +# 2. Chrome Sandbox support requires you set up and run as a non-root user (or you need to run google-chrome --no-sandbox). +# The debian-common.sh script can do this for you, or you can follow https://aka.ms/vscode-remote/containers/non-root + +USERNAME=${1:-"vscode"} +VNC_PASSWORD=${2:-"vscode"} +INSTALL_NOVNC=${3:-"true"} + +PACKAGE_LIST=" + xvfb \ + x11vnc \ + fluxbox \ + dbus-x11 \ + x11-utils \ + x11-xserver-utils \ + xdg-utils \ + fbautostart \ + xterm \ + eterm \ + tilix \ + nautilus\ + mousepad \ + seahorse \ + gnome-icon-theme \ + gnome-keyring \ + libx11-dev \ + libxkbfile-dev \ + libsecret-1-dev \ + libnotify4 \ + libnss3 \ + libxss1 \ + libgdm1 \ + libasound2 \ + xfonts-base \ + xfonts-terminus \ + fonts-noto \ + fonts-wqy-microhei \ + fonts-droid-fallback \ + python3-numpy \ + htop \ + ncdu \ + curl \ + ca-certificates\ + unzip \ + nano \ + locales" + +set -e + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +# Treat a user name of "none" or non-existant user as root +if [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then + USERNAME=root +fi + +# Function to run apt-get if needed +apt-get-update-if-needed() +{ + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + echo "Running apt-get update..." + apt-get update + else + echo "Skipping apt-get update." + fi +} + +# Ensure apt is in non-interactive to avoid prompts +export DEBIAN_FRONTEND=noninteractive + +apt-get-update-if-needed + +# On older Ubuntu, Tilix is in a PPA. On Debian Strech, its in backports +if [[ -z $(apt-cache --names-only search ^tilix$) ]]; then + apt-get install -y --no-install-recommends lsb-release + if [ "$(lsb_release -is)" = "Ubuntu" ]; then + apt-get install -y --no-install-recommends apt-transport-https software-properties-common + add-apt-repository -y ppa:webupd8team/terminix + else + echo "deb http://deb.debian.org/debian $(lsb_release -cs)-backports main" > /etc/apt/sources.list.d/$(lsb_release -cs)-backports.list + fi + apt-get update +fi + +# Install X11, fluxbox and VS Code dependencies +if ! dpkg -s ${PACKAGE_LIST} > /dev/null 2>&1; then + apt-get -y install --no-install-recommends ${PACKAGE_LIST} +fi + +# Check at least one locale exists +if ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then + echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen + locale-gen +fi + +# Install the Cascadia Code fonts - https://github.com/microsoft/cascadia-code +if [ ! -d "/usr/share/fonts/truetype/cascadia" ]; then + curl -sSL https://github.com/microsoft/cascadia-code/releases/download/v2008.25/CascadiaCode-2008.25.zip -o /tmp/cascadia-fonts.zip + unzip /tmp/cascadia-fonts.zip -d /tmp/cascadia-fonts + mkdir -p /usr/share/fonts/truetype/cascadia + mv /tmp/cascadia-fonts/ttf/* /usr/share/fonts/truetype/cascadia/ + rm -rf /tmp/cascadia-fonts.zip /tmp/cascadia-fonts +fi + +# Install noVNC +NOVNC_VERSION=1.2.0 +WEBSOCKETIFY_VERSION=0.9.0 +if [ "${INSTALL_NOVNC}" = "true" ] && [ ! -d "/usr/local/novnc" ]; then + mkdir -p /usr/local/novnc + curl -sSL https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.zip -o /tmp/novnc-install.zip + unzip /tmp/novnc-install.zip -d /usr/local/novnc + cp /usr/local/novnc/noVNC-${NOVNC_VERSION}/vnc_lite.html /usr/local/novnc/noVNC-${NOVNC_VERSION}/index.html + curl -sSL https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.zip -o /tmp/websockify-install.zip + unzip /tmp/websockify-install.zip -d /usr/local/novnc + ln -s /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION} /usr/local/novnc/noVNC-${NOVNC_VERSION}/utils/websockify + # Tweak websocketify to use python3 since python 2 may not be installed + sed -i -E "s/^python\s/\/usr\/bin\/python3 /g" /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION}/run + rm -f /tmp/websockify-install.zip /tmp/novnc-install.zip +fi + +# Set up folders for scripts and init files +mkdir -p /var/run/dbus /usr/local/etc/vscode-dev-containers/ /root/.fluxbox + +# Script to change resolution of desktop +tee /usr/local/bin/set-resolution > /dev/null \ +<< EOF +#!/bin/bash +RESOLUTION=\${1:-\${VNC_RESOLUTION:-1920x1080}} +DPI=\${2:-\${VNC_DPI:-96}} +IGNORE_ERROR=\${3:-"false"} +if [ -z "\$1" ]; then + echo -e "**Current Settings **\n" + xrandr + echo -n -e "\nEnter new resolution (WIDTHxHEIGHT, blank for \${RESOLUTION}, Ctrl+C to abort).\n> " + read NEW_RES + if [ "\${NEW_RES}" != "" ]; then + RESOLUTION=\${NEW_RES} + fi + if ! echo "\${RESOLUTION}" | grep -E '[0-9]+x[0-9]+' > /dev/null; then + echo -e "\nInvalid resolution format!\n" + exit 1 + fi + if [ -z "\$2" ]; then + echo -n -e "\nEnter new DPI (blank for \${DPI}, Ctrl+C to abort).\n> " + read NEW_DPI + if [ "\${NEW_DPI}" != "" ]; then + DPI=\${NEW_DPI} + fi + fi +fi +xrandr --fb \${RESOLUTION} --dpi \${DPI} > /dev/null 2>&1 +XRANDR_EXIT=$? +if [ \${XRANDR_EXIT} -ne 0 ] && [ IGNORE_ERROR != "true" ]; then + echo -e "\nFAILED TO SET RESOLUTION! (Code: ${XRANDR_EXIT})\n" + exit 1 +fi +echo -e "\nSuccess!\n" +EOF + +# Container ENTRYPOINT script +tee /usr/local/share/desktop-init.sh > /dev/null \ +<< EOF +#!/bin/bash +USERNAME=${USERNAME} +LOG=/tmp/container-init.log +# Execute the command it not already running +startInBackgroundIfNotRunning() +{ + log "Starting \$1." + echo -e "\n** \$(date) **" | sudoIf tee -a /tmp/\$1.log > /dev/null + if ! pidof \$1 > /dev/null; then + keepRunningInBackground "\$@" + while ! pidof \$1 > /dev/null; do + sleep 1 + done + log "\$1 started." + else + echo "\$1 is already running." | sudoIf tee -a /tmp/\$1.log > /dev/null + log "\$1 is already running." + fi +} +# Keep command running in background +keepRunningInBackground() +{ + (\$2 sh -l -c "while :; do echo [\\\$(date)] Process started.; \$3; echo [\\\$(date)] Process exited!; sleep 5; done 2>&1" | sudoIf tee -a /tmp/\$1.log > /dev/null & echo "\$!" | sudoIf tee /tmp/\$1.pid > /dev/null) +} +# Use sudo to run as root when required +sudoIf() +{ + if [ "\$(id -u)" -ne 0 ]; then + sudo "\$@" + else + "\$@" + fi +} +# Use sudo to run as non-root user if not already running +sudoUserIf() +{ + if [ "\$(id -u)" -eq 0 ] && [ "\${USERNAME}" != "root" ]; then + sudo -u \${USERNAME} "\$@" + else + "\$@" + fi +} +# Log messages +log() +{ + echo -e "[\$(date)] \$@" | sudoIf tee -a \$LOG > /dev/null +} +log "** SCRIPT START **" +# Start dbus. +log 'Running "/etc/init.d/dbus start".' +if [ -f "/var/run/dbus/pid" ] && ! pidof dbus-daemon > /dev/null; then + sudoIf rm -f /var/run/dbus/pid +fi +sudoIf /etc/init.d/dbus start 2>&1 | sudoIf tee -a /tmp/dbus-daemon-system.log > /dev/null +while ! pidof dbus-daemon > /dev/null; do + sleep 1 +done +# Set up Xvfb. +startInBackgroundIfNotRunning "Xvfb" sudoIf "Xvfb \${DISPLAY:-:1} +extension RANDR -screen 0 \${MAX_VNC_RESOLUTION:-1920x1080x24}" +# Start fluxbox as a light weight window manager. +startInBackgroundIfNotRunning "fluxbox" sudoUserIf "dbus-launch startfluxbox" +# Start x11vnc +startInBackgroundIfNotRunning "x11vnc" sudoIf "x11vnc -display \${DISPLAY:-:1} -rfbport \${VNC_PORT:-5901} -localhost -no6 -xkb -shared -forever" +# Set resolution +/usr/local/bin/set-resolution \${VNC_RESOLUTION:-1440x768} \${VNC_DPI:-96} true +# Spin up noVNC if installed and not runnning. +if [ -d "/usr/local/novnc" ] && [ "\$(ps -ef | grep /usr/local/novnc/noVNC*/utils/launch.sh | grep -v grep)" = "" ]; then + keepRunningInBackground "noVNC" sudoIf "/usr/local/novnc/noVNC*/utils/launch.sh --listen \${NOVNC_PORT:-6080} --vnc localhost:\${VNC_PORT:-5901}" + log "noVNC started." +else + log "noVNC is already running or not installed." +fi +# Run whatever was passed in +log "Executing \"\$@\"." +exec "\$@" +log "** SCRIPT EXIT **" +EOF + +echo "${VNC_PASSWORD}" > /usr/local/etc/vscode-dev-containers/vnc-passwd +touch /root/.Xmodmap +chmod +x /usr/local/share/desktop-init.sh /usr/local/bin/set-resolution + +tee /root/.fluxbox/apps > /dev/null \ +< /dev/null \ +< /dev/null \ +< + [exec] (Text Editor) { mousepad } <> + [exec] (Terminal) { tilix -w ~ -e $(readlink -f /proc/$$/exe) -il } <> + [exec] (Web Browser) { x-www-browser } <> + [submenu] (System) {} + [exec] (Set Resolution) { tilix -t "Set Resolution" -e bash /usr/local/bin/set-resolution } <> + [exec] (Top Processes) { tilix -t "Top" -e htop } <> + [exec] (Disk Utilization) { tilix -t "Disk Utilization" -e ncdu / } <> + [exec] (Passwords and Keys) { seahorse } <> + [exec] (Editres) {editres} <> + [exec] (Xfontsel) {xfontsel} <> + [exec] (Xkill) {xkill} <> + [exec] (Xrefresh) {xrefresh} <> + [end] + [config] (Configuration) + [workspaces] (Workspaces) +[end] +EOF + +# Set up non-root user (if one exists) +if [ "${USERNAME}" != "root" ]; then + touch /home/${USERNAME}/.Xmodmap + cp -R /root/.fluxbox /home/${USERNAME} + chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.Xmodmap /home/${USERNAME}/.fluxbox + chown ${USERNAME}:root /usr/local/share/desktop-init.sh /usr/local/bin/set-resolution /usr/local/etc/vscode-dev-containers/vnc-passwd +fi + +echo "Done!" diff --git a/.devcontainer/library-scripts/java-debian.sh b/.devcontainer/library-scripts/java-debian.sh new file mode 100644 index 00000000..04a1ca30 --- /dev/null +++ b/.devcontainer/library-scripts/java-debian.sh @@ -0,0 +1,47 @@ +JAVA_VERSION=${1:-"lts"} +export SDKMAN_DIR=${2:-"/usr/local/sdkman"} +USERNAME=${3:-"vscode"} +UPDATE_RC=${4:-"true"} + +set -e + +if [ "${JAVA_VERSION}" = "lts" ]; then + JAVA_VERSION="" +fi + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +if [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then + USERNAME=root +fi + +function updaterc() { + if [ "${UPDATE_RC}" = "true" ]; then + echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." + echo -e "$1" | tee -a /etc/bash.bashrc >> /etc/zsh/zshrc + fi +} + +export DEBIAN_FRONTEND=noninteractive + +if ! dpkg -s curl ca-certificates zip unzip sed > /dev/null 2>&1; then + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + apt-get update + fi + apt-get -y install --no-install-recommends curl ca-certificates zip unzip sed +fi + +if [ ! -d "${SDKMAN_DIR}" ]; then + curl -sSL "https://get.sdkman.io?rcupdate=false" | bash + chown -R "${USERNAME}" "${SDKMAN_DIR}" + updaterc "export SDKMAN_DIR=${SDKMAN_DIR}\nsource \${SDKMAN_DIR}/bin/sdkman-init.sh" +fi + +if [ "${JAVA_VERSION}" != "none" ]; then + su ${USERNAME} -c "source ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk install java ${JAVA_VERSION} && sdk flush archives && sdk flush temp" +fi + +echo "Done!" \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 04ab97c3..00000000 --- a/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.class - -bin -.metadata -.recommenders -.DS_Store - -# Package Files # -*.war -*.ear -TeachingKidsProgramming/.virtual_proctor.txt diff --git a/.metals/metals.lock.db b/.metals/metals.lock.db new file mode 100644 index 00000000..56cbdef4 --- /dev/null +++ b/.metals/metals.lock.db @@ -0,0 +1,6 @@ +#FileLock +#Tue Sep 15 16:43:00 CDT 2020 +hostName=localhost +id=17493b7814655ac7e0efffedc014311fc7d956d4d59 +method=file +server=localhost\:53361 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..6d612c8d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "java.configuration.updateBuildConfiguration": "automatic", + "java.dependency.packagePresentation": "hierarchical", + "java.project.referencedLibraries": [ + "lib/**/*.jar", + "TKPJava/src/jars/**/*.jar", + "/root/workspace/TeachingKidsProgramming.Java/**/*.jar" + ], + "files.watcherExclude": { + "**/target": true + }, + "java.project.sourcePaths": [ + "TKPJava/src/main/java/org/verify-TKP", + "TKPJava" + ] +} \ No newline at end of file diff --git a/TeachingKidsProgramming/spun_code_style.xml b/.vscode/tkp_eclipse_code_style.xml similarity index 100% rename from TeachingKidsProgramming/spun_code_style.xml rename to .vscode/tkp_eclipse_code_style.xml diff --git a/LICENSE.md b/LICENSE.md index fed464b1..c3ffc879 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (c) 2011 Teaching Kids Programming (http://www.teachingkidsprogramming.org). All rights reserved. + Copyright (c) 2020 Teaching Kids Programming (http://www.teachingkidsprogramming.org). All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Ninite Eclipse Installer.exe b/Ninite Eclipse Installer.exe deleted file mode 100644 index de31d0d5..00000000 Binary files a/Ninite Eclipse Installer.exe and /dev/null differ diff --git a/Ninite JDK x64 8 Installer.exe b/Ninite JDK x64 8 Installer.exe deleted file mode 100644 index 032fb41a..00000000 Binary files a/Ninite JDK x64 8 Installer.exe and /dev/null differ diff --git a/README.md b/README.md index 7fa20ecd..edd24544 100644 --- a/README.md +++ b/README.md @@ -1,205 +1,3 @@ -# Get Started With TKP - -Setup your computer for TKP based on it's operating system: - -* [Windows](#windows) -* [Mac](#mac) -* [Linux](#linux) - -### Windows - -1. **Create** a new folder named `TKPSource` (no spaces in the folder name) at the top level of your `C:` drive. Example: `C:\TKPSource`. - - ![Create C:\TKPSource](/images/01CreateFolder.png?raw=true) - -1. **Download** the TKP zip file from this site by clicking the green `Clone or Download` button on the middle right side of this page, and then click the blue download zip button (or use the link directly below this line). Wait for the download to complete. - - [![download](/images/download_zip.png?raw=true)](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java/archive/master.zip) - -1. **Move** the zip file from your **Downloads** folder to the **C:\TKPSource** folder. The name of the downloaded file is `TeachingkidsProgramming.Java-master.zip` - - ![Move zip to C:\TKPSource](/images/02MoveZip.png?raw=true) - -1. **Unzip** the downloaded file. Right click on the zip file, and choose `Extract All...`. Next click `Extract` to create the TKP folder. - - ![Extract Zip](/images/03ExtractAll.png?raw=true) - -1. **Open** the unzipped TKP folders and find the **'TKP_Launcher.jar'** file. - - ![TKP Launcher](/images/04TKPLauncher.png?raw=true) - -1. **Run** the `TKP_Launcher.jar` file by double-clicking it. Wait for it to run. *Tip* if the jar wont run, double check that you are double-clicking it from the extracted **folder** and not inside the **zip**. - - If the jar file runs ok, then Eclipse will launch with the TKP workspace open. A successful install should look like the screenshot below: (you can test with two lines of code below) - - ```java - Tortoise.show(); - Tortoise.move(50); - ``` - - ![screenshot of Eclipse](/images/20Success.png?raw=true) - - If an error MessageBox pops up, you probably just need a little more setup, keep reading. - - - ![Java Missing](/images/05NoJava.png?raw=true) - -1. **Run** the "Ninite" installer for Java. There are two, but only one is appropriate for your computer. Look in the `C:\` folder. Do you have a folder called `Program Files (x86)`? - - ![64-bit](/images/06_64bit.png?raw=true) - - If so, then double-click `Ninite JDK x64 8 Installer.exe`. Otherwise, double-click `Ninite JDK 8 Installer.exe`. (If you see a `Security Warning` click `Run`. If you see a `User Account Control` prompt click `Yes`). When the Ninite Java install finishes, try double-clicking the `TKP_Launcher.jar` again. - - If it works, great! Otherwise, you might see a message like the one below. Keep reading for more setup. - - ![Eclipse Missing](/images/07NoEclipse.png?raw=true) - -1. **Run** the "Ninite" installer for Eclipse. There is only one installer for eclipse, called `Ninite Eclipse Installer.exe`. Double-click the eclipse installer (If you see a `Security Warning` click `Run`. If you see a `User Account Control` prompt click `Yes`). When the Ninite Java install finishes, try double-clicking the `TKP_Launcher.jar` again. - - If it works, great! Otherwise, visit the [Fixing Installation Errors](#troubleshooting) section below for more tips. - -### Mac - -1. **Create** a new folder named `TKPSource` (no spaces in the folder name) in your `Documents` folder. Example: `/Users/james/Documents/TKPSource`. - - ![Create ~/TKPSource](/images/08CreateFolder.png?raw=true) - -1. **Download** the TKP zip file from this site by clicking the `Download ZIP` button on the middle right side of this page (or use the link directly below this line). Wait for the download to complete. - - [![download zip button][2]][1] - -1. **Move** the zip file from your **Downloads** folder to the **TKPSource** folder. The name of the downloaded file is `TeachingkidsProgramming.Java-master.zip` - - ![Move zip to TKPSource](/images/09MoveZip.png?raw=true) - -1. **Unzip** the downloaded file. Right click on the zip file, and choose `Open` to create the TKP folder. - - ![Extract Zip](/images/10Open.png?raw=true) - -1. **Open** the unzipped TKP folders and find the **TKP_Launcher.jar** file. - - ![TKP Launcher](/images/11TKPLauncher.png?raw=true) - -1. **Run** the `TKP_Launcher.jar` file by double-clicking it. Wait for it to run. *Tip* if the jar wont run, double check that you are double-clicking it from the extracted **folder** and not inside the **zip**. - - If the jar file runs ok, then Eclipse will launch with the TKP workspace open. A successful install should look like the screenshot below: (you can test with two lines of code below) - - ```java - Tortoise.show(); - Tortoise.move(50); - ``` - - ![screenshot of Eclipse](/images/20Success.png?raw=true) - - If an error MessageBox pops up, you probably just need a little more setup, keep reading. - - ![Not Trusted](/images/12Untrusted.png?raw=true) - -1. **Open** the Mac `System Preferences` and choose `Security & Privacy`. - - ![Settings](/images/13Settings.png?raw=true) - - Click `Open Anyway`, then `Open`. This will allow the TKP launcher to run in the future, and Mac will immediately try to run the launcher again. - - ![Open Anyway](/images/14OpenAnyway.png?raw=true) - - If it works, great! Otherwise, you might see a message like the one below. Keep reading for more setup. - - ![Java Missing](/images/15NoJava.png?raw=true) - -1. **Download** Java 8. Click the `More Info...` button (shown above) to go to Oracle's download page. There are several download options, choose `JDK` (indicated below). - - ![Choose JDK](/images/16JDK.png?raw=true) - - On the next page there is a table of files you can download. First, accept the Java license by choosing `Accept License Agreement`. Now, find `Mac OS X x64` in the table and download the `dmg` file from the same row. - - ![Choose Mac DMG](/images/17JDK2.png?raw=true) - - Wait for it to download, then double-click the dmg to open it. Double click the `pkg` file inside the `dmg`, then click `Continue` then `Install` in the wizard that appears. Enter your password if prompted, and wait for the installation to complete. - - Next, try launching the `TKP_Launcher.jar` by double-clicking it. If it works, great! Otherwise, you might see a message like the one below. Keep reading for more setup. - - ![Eclipse Missing](/images/18NoEclipse.png?raw=true) - -1. **Download** [Eclipse Luna][3]. To extract the eclipse files, right-click on the `eclipse-java-luna-SR2-macosx-cocoa-x86_64.tar.gz` file and choose `Open`. Next, drag the `eclipse` folder to `Applications` for your username, i.e. //Applications. - - ![Move Eclipse](/images/19Eclipse.png?raw=true) - - When you have put `eclipse` into `Applications` try launching TKP again by double-clicking `TKP_Launcher.jar`. If it works, great! Otherwise, visit the [Fixing Installation Errors](#troubleshooting) section below for more tips. - -### Linux - -1. **Ubuntu** - - To install on Ubuntu, open a terminal window and run the following command: - - ```bash - source <(curl -L -s http://tinyurl.com/hzvqvck) - ``` - - This command will download everything needed for TKP and create a shortcut on your desktop. - -Eclipse should run automatically and the first lesson from TKP will open. - -If you are having troubles reading the text inside the "JavaDoc" panel, you might need to change your system colors. This can be done by using the "color chooser" app. Just type: - -```bash -sudo apt install gnome-color-chooser -gnome-color-chooser -``` - -You will need to go to the "Specific" tab and change your tooltip colors. - - -## Fixing Installation Errors - -We're sorry that you are having trouble getting started with TKP. Below you will find a few more troubleshooting tips that we have used to resolve issues in the past. - -###Correct version of Java (7 or higher) not installed - -We test the standard installation steps using "clean" computers with no software installed except what comes with Windows or OSX. However, your computer might have an older version of Java on it that we don't support. - -To validate the version of Java that is installed, go to [this website](http://java.com/en/download/installed8.jsp) and click the 'validate' button. **Note** this website will not work in Google's Chrome browser, so you may need to visit it in another browser (Safari/Firefox/Internet Explorer/etc). - -If the reported version of your Java installation is less than 7, then update Java to the version that Oracle recommends. - -###Correct version of Eclipse (Luna) not installed - -We test the standard installation steps using "clean" computers with no software installed except what comes with Windows or OSX. However, your computer might have an older version of eclipse on it that we don't support. - -Eclipse installations have friendly names (examples: Indigo, Kepler, Luna) that indicate their version. You can see this name when eclipse starts. - -![Eclipse Luna](/images/21Luna.png?raw=true) - -We test TKP with `Luna`. The friendly names are in alphabetical order, so if your version starts with a letter that comes before `L`, then you are using an older version of eclipse and should update to Luna. If you are using a version of eclipse that comes after `L`, then it _should_ work, but we haven't yet tested that version, you may want to try Luna. - -We recommend that you delete your current version of eclipse. (Advanced users can rename it, but we won't cover that here). On **Windows**, delete `C:\eclipse`. On **Mac** delete `eclipse` from `Applications`. Next, go back to the installation instructions for [Windows](#wineclipse) or [Mac](#maceclipse) to setup Luna. - -###Customized TKP workspace did not open in Eclipse. - -Open Eclipse and change the default workspace directory, by clicking on `File` then choosing `Switch Workspace` and then `Open...`. Navigate to the `\TeachingKidsProgramming.Java\TeachingKidsProgramming` folder (under `C:\TKPSource` on **Windows**, or `Documents\TKPSource` on **Mac**). After you do this, then your `TeachingKidsProgramming.Java` should include the following folders: - -* `\.metadata` -* `\TeachingKidsProgramming` - -###Unable to write to file system location(s) -This general installation failure can occur if your school has "locked down" permissions to student lab computers. - -Try to `run as administrator` for **Windows**, or `run as root` for **Mac** and this may allow the downloaded TKP files to unzip. - -Some schools create a virtual (sometimes shared) `C:\` drive. If the drive is shared, eclipse should still be installed to `C:\`, but `TKPSource` should be created in each student's `C:\temp` directory. - -###Still Stuck? - -Please consider writing a description of the errors/problems you are seeing and sharing it with us by opening a GitHub issue. You can be a detailed as you like, and your story will help us make TKP better. - -You can create a issue by following this link (GitHub account required): [Create An Issue][4] - -Or you can [email us from this page](http://teachingkidsprogramming.org/contact/) and we will create the issue for you (no account required). - - [1]: https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java/archive/master.zip - [2]: https://dl.dropboxusercontent.com/u/41301272/downloadZip.png - [3]: https://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/luna/SR2/eclipse-java-luna-SR2-macosx-cocoa-x86_64.tar.gz - [4]: https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java/issues/new - +### TKPJava for Codespaces +This is the Repo/branch for the Github Codespaces test for TKPJava \ No newline at end of file diff --git a/TeachingKidsProgramming/.classpath b/TKPJava/.classpath similarity index 70% rename from TeachingKidsProgramming/.classpath rename to TKPJava/.classpath index f253a67e..1e627dc6 100644 --- a/TeachingKidsProgramming/.classpath +++ b/TKPJava/.classpath @@ -8,5 +8,9 @@ + + + + diff --git a/TeachingKidsProgramming/.gitignore b/TKPJava/.gitignore similarity index 100% rename from TeachingKidsProgramming/.gitignore rename to TKPJava/.gitignore diff --git a/TeachingKidsProgramming/.settings/org.eclipse.jdt.core.prefs b/TKPJava/.settings/org.eclipse.jdt.core.prefs similarity index 100% rename from TeachingKidsProgramming/.settings/org.eclipse.jdt.core.prefs rename to TKPJava/.settings/org.eclipse.jdt.core.prefs diff --git a/TeachingKidsProgramming/src/jars/commons-logging-1.2.jar b/TKPJava/src/jars/commons-logging-1.2.jar similarity index 100% rename from TeachingKidsProgramming/src/jars/commons-logging-1.2.jar rename to TKPJava/src/jars/commons-logging-1.2.jar diff --git a/TKPJava/src/jars/hamcrest-core-1.3.jar b/TKPJava/src/jars/hamcrest-core-1.3.jar new file mode 100644 index 00000000..9d5fe16e Binary files /dev/null and b/TKPJava/src/jars/hamcrest-core-1.3.jar differ diff --git a/TeachingKidsProgramming/src/jars/httpclient-4.3.5.jar b/TKPJava/src/jars/httpclient-4.3.5.jar similarity index 100% rename from TeachingKidsProgramming/src/jars/httpclient-4.3.5.jar rename to TKPJava/src/jars/httpclient-4.3.5.jar diff --git a/TeachingKidsProgramming/src/jars/httpcore-4.4.1.jar b/TKPJava/src/jars/httpcore-4.4.1.jar similarity index 100% rename from TeachingKidsProgramming/src/jars/httpcore-4.4.1.jar rename to TKPJava/src/jars/httpcore-4.4.1.jar diff --git a/TeachingKidsProgramming/src/jars/httpmime-4.4.1.jar b/TKPJava/src/jars/httpmime-4.4.1.jar similarity index 100% rename from TeachingKidsProgramming/src/jars/httpmime-4.4.1.jar rename to TKPJava/src/jars/httpmime-4.4.1.jar diff --git a/TKPJava/src/jars/javax.servlet-api-3.1.0.jar b/TKPJava/src/jars/javax.servlet-api-3.1.0.jar new file mode 100644 index 00000000..6b14c3d2 Binary files /dev/null and b/TKPJava/src/jars/javax.servlet-api-3.1.0.jar differ diff --git a/TKPJava/src/jars/junit-4.13.jar b/TKPJava/src/jars/junit-4.13.jar new file mode 100644 index 00000000..acc3c432 Binary files /dev/null and b/TKPJava/src/jars/junit-4.13.jar differ diff --git a/TKPJava/src/jars/velocity-dep-1.4.jar b/TKPJava/src/jars/velocity-dep-1.4.jar new file mode 100644 index 00000000..375712b0 Binary files /dev/null and b/TKPJava/src/jars/velocity-dep-1.4.jar differ diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/Tortoise.java b/TKPJava/src/main/java/org/teachingextentions/logo/Tortoise.java new file mode 100644 index 00000000..b2492ab3 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/Tortoise.java @@ -0,0 +1,401 @@ +package src.main.java.org.teachingextentions.logo; + +import java.awt.Color; + +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.TurtleWindow; +import src.main.java.org.teachingextentions.logo.Turtle.Animals; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Text; +import src.main.java.org.teachingextentions.logo.utils.PizzaUtils.Pizza; +import src.main.java.org.teachingextentions.logo.utils.PizzaUtils.Topping; +import src.main.java.org.teachingextentions.logo.utils.VirtualProctorUtils.*; + +/** + * A tortoise drawing a line + * The Tortoise allows you to draw lines and shapes by moving it around on the window + */ +public class Tortoise +{ + private Topping topping; + /** + * Displays the Tortoise + *
Example: {@code Tortoise.show()}
+ */ + public static void show() + { + turtle().show(); + } + /** + * Gets the name for the tortoise + *
Example: {@code String name = Tortoise.getName("Anita Borg");}
+ * + * @return the name for the Tortoise + */ + public static String getName() + { + return turtle().getName(); + } + /** + * Sets the name for the tortoise + *
Example: {@code Tortoise.setName("Ada Lovelace")}
+ * + * @param name + * The name for the Tortoise + */ + public static void setName(String name) + { + turtle().setName(name); + } + /** + * Gets the speed that the tortoise moves + *
Example: {@code int speed = Tortoise.getSpeed(8);}
+ * + * @return the speed the Tortoise is currently set to + */ + public static int getSpeed() + { + return turtle().getSpeed(); + } + /** + * Sets the speed the tortoise moves + *
Example: {@code Tortoise.setSpeed(8)}
+ * + * @param speed + * The speed from 1 (slowest) to 10 (fastest) + */ + public static void setSpeed(int speed) + { + turtle().setSpeed(speed); + } + /** + * Moves the Tortoise Forward the number of pixels specified.
+ *
Example: {@code Tortoise.move(72)}
+ * + * @param lengthInPixels + * The number of pixels to move. Negative numbers will move the + * Tortoise backwards. + */ + public static void move(Number lengthInPixels) + { + turtle().move(lengthInPixels); + } + /** + * Turns the Tortoise to the right (clockwise) the degrees specified.
+ *
Example: {@code Tortoise.turn(90)}
+ * + * @param degreesToTheRight + * The degrees to turn. Negative numbers will move the Tortoise to + * the left (counter-clockwise) + */ + public static void turn(Number degreesToTheRight) + { + turtle().turn(degreesToTheRight.doubleValue()); + } + /** + * Gives you access to the window the + * Tortoise is moving on so you can do things like change it's color.
+ * Example: {@code TurtlePanel panel = Tortoise.getBackgroundWindow()} + * @return the (program) window that the Tortoise is moving on + */ + public static TurtleWindow getBackgroundWindow() + { + return turtle().getBackgroundWindow(); + } + /** + * Gets the current width of the pen drawn by the Tortoise.
+ *
Example: {@code width = Tortoise.getPenWidth()}
+ * + * @return the width of the pen stroke + */ + public static int getPenWidth() + { + return turtle().getPenWidth(); + } + /** + * Sets the width of the pen drawn by the Tortoise.
+ *
Example: {@code Tortoise.setPenWidth(2)}
+ * + * @param width + * the width of the pen stroke + */ + public static void setPenWidth(Number width) + { + turtle().setPenWidth(width.intValue()); + } + /** + * Gets the current color of the pen drawn by the Tortoise.
+ *
Example: {@code pen = Tortoise.getPenColor()}
+ * + * @return the color of the pen stroke + */ + public static Color getPenColor() + { + return turtle().getPenColor(); + } + /** + * Sets the color of the line drawn by the Tortoise.
+ *
Example: {@code Tortoise.setPenColor(PenColors.Reds.Red)}
+ * + * @param color + * the color of the line drawn + * @see PenColors + */ + public static void setPenColor(Color color) + { + turtle().setPenColor(color); + } + /** + * Gets the current position of the Tortoise on the y axis.
+ * (0,0) is the top left of the screen
+ *
Example: {@code y = Tortoise.getY()}
+ * + * @return y the position in pixels of the Tortoise on the Y axis + */ + public static int getY() + { + return turtle().getY(); + } + /** + * Sets the position of the Tortoise on the y axis.
+ * (0,0) is the top left of the screen
+ *
Example: {@code Tortoise.setY(30);}
+ * + * @param y + * the position in pixels of the Tortoise on the Y axis + */ + public static void setY(int y) + { + turtle().setY(y); + } + /** + * Gets the current position of the Tortoise on the x axis.
+ * (0,0) is the top left of the screen
+ *
Example: {@code x = Tortoise.getX()}
+ * + * @return x the position in pixels of the Tortoise on the X axis + */ + public static int getX() + { + return turtle().getX(); + } + /** + * Sets the position of the Tortoise on the x axis.
+ * (0,0) is the top left of the screen
+ *
Example: {@code Tortoise.setX(30);}
+ * + * @param x + * the position in pixels of the Tortoise on the X axis + */ + public static void setX(int x) + { + turtle().setX(x); + } + /** + * Gets the current heading of the Tortoise.
+ * 0 degrees is due north.
+ * 90 degrees is due east.
+ *
Example: {@code angle = Tortoise.getAngleInDegrees()}
+ * + * @return the angle in degrees of the Tortoise + */ + public static double getAngle() + { + return turtle().getAngleInDegrees(); + } + /** + * Sets the angle the Tortoise is facing.
+ * 0 is straight up (like 'North')
+ *
Example: {@code Tortoise.setAngle(42);}
+ * + * @param angle + * the angle in degrees + */ + public static void setAngle(int angle) + { + turtle().setAngleInDegrees(angle); + } + /** + * Changes the type of animal you are using.
+ *
Example: {@code Tortoise.setAnimal(Animals.Spider);}
+ * + * @param animal the animal you want to use + * @see Animals + */ + public static void setAnimal(Animals animal) + { + turtle().setAnimal(animal); + } + /** + * Blows up your turtle!
+ *
Example: {@code Tortoise.explode(Animals.ExplodedTurtle);}
+ * + * @see Animals + */ + public static void explode() + { + turtle().setAnimal(Animals.ExplodedTurtle); + } + /** + * Makes it so the tortoise will not draw a line of color out of its butt.
+ * Example: {@code Tortoise.penUp()} + */ + public static void setPenUp() + { + turtle().penUp(); + } + /** + * Makes it so a line of color out of will trail from the Tortoise.
+ * Example: {@code Tortoise.penDown()} + */ + public static void setPenDown() + { + turtle().penDown(); + } + /** + * Removes everything from the window.
+ * Example: {@code Tortoise.clearWindow()} + */ + public static void clear() + { + turtle().clear(); + turtle().getBackgroundWindow().setTurtle(turtle()); + } + /** + * Hides the tortoise, you will still see the pen markings it made before and after it's hidden.
+ * Example: {@code Tortoise.hide()} + */ + public static void hide() + { + turtle().hide(); + } + private static Turtle turtle() + { + return TortoiseUtils.getTurtle(); + } + /** + * Moves the Tortoise to a particular spot on the canvas.
+ *
Example: {@code Tortoise.moveTo(100,200);}
+ * + * @param x + * the x position + * @param y + * the y position + */ + public static void moveTo(int x, int y) + { + turtle().moveTo(x, y); + } + public static TurtleWindow ___() + { + return new TurtleWindow(); + } + /** + * Makes a cool shape fast + *
Example: {@code tortoise.drawShape(6,PenColors.Reds.Red, 50, 20)}
+ * @param sides + * the number of sides + * @param color + * a snazzy line color + * @param length + * the bigger the better + * @param width + * make a thick line - it's cool + */ + public static void drawShape(int sides, Color color, int length, int width) + { + Tortoise.show(); + Tortoise.setSpeed(7); + Tortoise.getBackgroundWindow().getCanvas().setBackground(PenColors.Yellows.Goldenrod); + new Text("TKP Java - Make Some Shapes!").setTopLeft(225, 50).addTo(Tortoise.getBackgroundWindow()); + for (int i = 0; i < sides; i++) + { + Tortoise.setPenColor(color); + Tortoise.setPenWidth(width); + Tortoise.move(length); + Tortoise.turn(360 / sides); + } + VirtualProctor.setClassName("Grace Hopper's Class"); + VirtualProctor.setName("Jean Bartik"); + } + /** + * Draws an entire Tortoise -- fast! + *
Example: {@code tortoise.drawTortoise()}
+ */ + public static void drawTortoise() + { + Tortoise.show(); + Tortoise.setSpeed(9); + Tortoise.getBackgroundWindow().setBackground(PenColors.Greens.DarkSeaGreen); + new Text("TKP Java - It's the Tortoise!").setTopLeft(200, 75).addTo(Tortoise.getBackgroundWindow()); + Tortoise.setPenColor(PenColors.Greens.Green); + Tortoise.setPenWidth(3); + makeTortoiseBody(); + Tortoise.setPenColor(PenColors.Browns.Brown); + Tortoise.turn(-65); + Tortoise.makeTortoiseLeg(); + Tortoise.turn(90); + Tortoise.move(150); + Tortoise.turn(-90); + Tortoise.makeTortoiseLeg(); + } + private static void makeTortoiseLeg() + { + for (int i = 0; i < 4; i++) + { + Tortoise.move(35); + Tortoise.turn(90); + } + } + private static void makeTortoiseBody() + { + Tortoise.turn(-90); + Tortoise.move(255); + Tortoise.turn(135); + Tortoise.move(135); + Tortoise.turn(45); + Tortoise.move(120); + Tortoise.turn(45); + Tortoise.move(70); + Tortoise.turn(-90); + Tortoise.move(35); + Tortoise.turn(45); + Tortoise.move(60); + Tortoise.turn(65); + Tortoise.move(50); + Tortoise.turn(115); + Tortoise.move(65); + Tortoise.turn(-25); + Tortoise.move(65); + } + public static void setVisible(boolean b) + { + turtle().setFrameVisible(b); + turtle().setPanelVisible(b); + } + /** + * Checks if a tortoise can eat a slice of a pizza + *
Example: {@code tortoise.eatPizza(pizza)}
+ * + * @param pizza + * the pizza + * @return whether or not there is pizza left to eat that a tortoise likes + */ + public boolean eatPizza(Pizza pizza) + { + if (!pizza.takeSlice()) { return false; } + if (this.topping == null) { return true; } + if (this.topping != Topping.Cheese) { return pizza.hasTopping(topping); } + return pizza.wasCooked() && pizza.hasTopping(topping); + } + /** + * Checks to see if a tortoise likes a particular kind of pizza topping + *
Example: {@code tortoise.likesTopping(topping)}
+ * + * @param topping + * the topping + */ + public void likesTopping(Topping topping) + { + this.topping = topping; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/TortoiseUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/TortoiseUtils.java new file mode 100644 index 00000000..eac891e8 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/TortoiseUtils.java @@ -0,0 +1,51 @@ +package src.main.java.org.teachingextentions.logo; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.Approvals; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalResults; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; + +public class TortoiseUtils { + private static Turtle TURTLE = new Turtle(); + + /** + * Captures an image of the result of your program and displays it to you + */ + public static void verify() { + try { + Approvals.verify(TURTLE.getImage()); + } catch (Exception e) { + throw ObjectUtils.throwAsError(e); + } finally { + TortoiseUtils.resetTurtle(); + } + } + + public static void resetTurtle() { + TURTLE = new Turtle(); + } + + public static void setOrientation(int x, int y, int angle) { + TURTLE.setX(x); + TURTLE.setY(y); + TURTLE.setAngleInDegrees(angle); + } + + public static Turtle getTurtle() { + return TURTLE; + } + + public static void setTurtle(Turtle turtle) { + TortoiseUtils.TURTLE = turtle; + } + + public static void verifyForOs() { + ApprovalResults.UniqueForOs(); + verify(); + } + + public static void writeMessage(String string, int x, int y) { + TURTLE.setX(x); + TURTLE.setY(y); + TURTLE.print(string); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/Turtle.java b/TKPJava/src/main/java/org/teachingextentions/logo/Turtle.java new file mode 100644 index 00000000..1ec2b3fa --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/Turtle.java @@ -0,0 +1,408 @@ +package src.main.java.org.teachingextentions.logo; + +import java.awt.Color; +import java.awt.Point; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JFrame; + +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.ProgramWindow; +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.Sound; +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.TurtleWindow; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ThreadLauncher; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.Action0; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.Saver; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.SavingException; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.AngleCalculator; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.DeltaCalculator; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.TurtleFrame; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.LineSegment; + +/** + * A turtle drawing a line + * The Turtle allows you to draw lines and shapes by moving it around on the window, and you can put more than one turtle on the same window... + */ +public class Turtle +{ + public static final int TEST_SPEED = Integer.MIN_VALUE; + private static final double MAX_MOVE_AMOUNT = 5.0; + private String DEFAULT_NAME = "Grace Hopper"; + public TurtleWindow panel = new TurtleWindow(); + public List trail = new ArrayList(); + private double x = 640 / 2; + private double y = 480 / 2; + private double angleInDegrees = 0; + private TurtleFrame frame = new TurtleFrame(); + private int speed = 1; + private Color color = Color.black; + private int width = 2; + private boolean penDown = true; + private boolean hidden; + private Animals animal; + private Sound sound = new Sound(); + private String name = DEFAULT_NAME; + public BufferedImage getImage() + { + BufferedImage image = panel.getWindowImage(); + clear(); + return image; + } + public void clear() + { + trail.clear(); + if (panel != null) + { + panel.getCanvas().clear(); + } + } + public void setPanel(TurtleWindow panel) + { + this.panel = panel; + } + public int getX() + { + return (int) x; + } + public void setX(Number x) + { + this.x = x.doubleValue(); + } + public int getY() + { + return (int) y; + } + public void setY(Number y) + { + this.y = y.doubleValue(); + } + public double getAngleInDegrees() + { + return angleInDegrees; + } + public void setAngleInDegrees(double angleInDegrees) + { + this.angleInDegrees = angleInDegrees; + } + public void turn(double amount) + { + double max = getTurnAmount(amount); + Saver s = new Turner(); + animate(amount, max, s); + } + private double getTurnAmount(double amount) + { + amount = Math.abs(amount); + if (getSpeed() == TEST_SPEED) { return amount; } + return amount / (11 - getSpeed()); + } + private void animate(double amount, double max, Saver s) + { + double sign = amount > 0 ? 1 : -1; + amount = Math.abs(amount); + while (amount > max) + { + s.save(max * sign); + refreshPanel(); + amount -= max; + } + s.save(amount * sign); + refreshPanel(); + } + private void refreshPanel() + { + refreshPanel(panel); + } + private void refreshPanel(ProgramWindow panel) + { + long delay = getDelay(); + if (delay != TEST_SPEED) + { + panel.repaint(); + try + { + Thread.sleep(delay); + } + catch (InterruptedException e) + { + // do nothing + } + } + } + private long getDelay() + { + if (getSpeed() == 10) { return 1; } + if (getSpeed() == TEST_SPEED) { return TEST_SPEED; } + return 100 / getSpeed(); + } + public String getName() + { + return name; + } + /** + * Sets the name for a turtle instance + *

Example: {@code myTurtle.setName(name)}

+ * + * @param name + * Your turtle's name + */ + public void setName(String name) + { + this.name = name; + } + public int getSpeed() + { + return speed; + } + /** + * Sets the speed that a turtle instance moves + *

Example: {@code myTurtle.setSpeed(speed)}

+ * + * @param speed + * The speed from 1 (slowest) to 10 (fastest) + */ + public void setSpeed(int speed) + { + if (speed != TEST_SPEED) + { + if (speed < 1 || 10 < speed) { throw new RuntimeException(String.format( + "I call shenanigans!!!\nThe speed '%s' is not between the acceptable range of [1-10]\nPerhaps you should read the documentation", + speed)); } + } + this.speed = speed; + } + public double getHeadingInDegrees() + { + return angleInDegrees; + } + /** + * Sets the distance that a turtle instance moves in pixels + *

Example: {@code myTurtle.move(100)}

+ * + * @param amount + * The distance that your turtle moves in pixels. Negative numbers will move your turtle backwards + */ + public void move(Number amount) + { + double max = MAX_MOVE_AMOUNT; + Saver s = penDown ? new Mover(new Point(getX(), getY())) : new EmptyMover(); + animate(amount.doubleValue(), max, s); + } + private void moveWithoutAnimation(Double save) + { + DeltaCalculator calculator = new DeltaCalculator(this.angleInDegrees, save); + x += calculator.getX(); + y += calculator.getY(); + } + public LineSegment[] getTrail() + { + return trail.toArray(new LineSegment[0]); + } + public Color getPenColor() + { + return color; + } + public void setPenColor(Color color) + { + this.color = color; + } + public int getPenWidth() + { + return width; + } + public void setPenWidth(int width) + { + this.width = width; + } + public void show() + { + this.panel.init(this, this.frame); + hidden = false; + this.setFrameVisible(true); + this.setPanelVisible(true); + refreshPanel(panel); + } + public TurtleWindow getBackgroundWindow() + { + return panel; + } + /** + * Sets the animal + *

Example: {@code myTurtle.setAnimal(Animals.spider)}

+ * + * @param animal + * The type of animal that appears on your window + */ + public void setAnimal(Animals animal) + { + refreshPanel(); + getBackgroundWindow().setAnimal(animal); + this.animal = animal; + } + public void penUp() + { + penDown = false; + } + public void penDown() + { + penDown = true; + } + public void print(String string) + { + + } + public void speak() + { + this.sound.playSound(); + } + public void hide() + { + hidden = true; + } + public boolean isHidden() + { + return hidden; + } + public void moveTo(final int x, final int y) + { + ThreadLauncher.launch(new Action0() + { + @Override + public void call() + { + moveSynchronized(x, y); + } + }); + } + public void moveSynchronized(int x, int y) + { + AngleCalculator calculator = new AngleCalculator(getX(), getY(), x, y); + double angleOfWherePointIs = calculator.getDegreesWith0North(); + double direction = angleOfWherePointIs - getAngleInDegrees(); + turn(direction); + // move the turtle the distance to the x y point + double distance = new Point(x, y).distance(getX(), getY()); + move(distance); + } + /** + * Draws a triangle of a specified size and orientation + *

Example: {@code myTurtle.drawTriangle(size)}

+ * + * @param size + * The size of a side of the triangle, negative numbers draw an upside down triangle + */ + public void drawTriangle(int size) + { + for (int i = 1; i <= 3; i++) + { + this.turn(360 / 3); + this.move(size); + } + } + /** + * Draws a star of a specified size + *

Example: {@code myTurtle.drawStar(size)}

+ * + * @param size + * The size of a side of the star + */ + public void drawStar(int size) + { + for (int i = 1; i <= 5; i++) + { + this.turn(360 / 2.5); + this.move(size); + } + } + public boolean isDead() + { + return this.animal == Animals.ExplodedTurtle; + } + /** + * Draws a lightning bolt of a specified length + *

Example: {@code myTurtle.drawLightning(length)}

+ * + * @param length + * The length of a lightning bolt + */ + public void drawLightning(int length) + { + this.setX(50); + this.setY(350); + this.setSpeed(10); + for (int i = 1; i < 5; i++) + { + this.setPenWidth(i * 4); + this.turn(65 + i); + this.move(length); + this.turn(-65); + this.move(length); + } + } + public void setFrameVisible(boolean b) + { + this.frame.setVisible(b); + } + public void setPanelVisible(boolean b) + { + panel.setVisible(b); + } + public void setFrame(JFrame frame2) + { + this.frame = new TurtleFrame(frame2); + } + public void setSound(Sound sound) + { + this.sound = sound; + } + /** + * Current types are: ExplodedTurtle, Turtle, Spider, Squid, Unicorn + */ + public enum Animals { + ExplodedTurtle, Turtle, Spider, Squid, Unicorn + } + private class Turner implements Saver + { + @Override + public Double save(Double save) throws SavingException + { + smallTurn(save); + return save; + } + private void smallTurn(double i) + { + angleInDegrees += i; + } + } + private class Mover implements Saver + { + private final Point starting; + private LineSegment line = null; + public Mover(Point point) + { + this.starting = point; + } + @Override + public Double save(Double save) throws SavingException + { + moveWithoutAnimation(save); + if (line != null) + { + trail.remove(line); + } + line = new LineSegment(color, starting, new Point(getX(), getY()), width); + trail.add(line); + return save; + } + } + private class EmptyMover implements Saver + { + @Override + public Double save(Double save) throws SavingException + { + moveWithoutAnimation(save); + return save; + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/Unicorn.java b/TKPJava/src/main/java/org/teachingextentions/logo/Unicorn.java new file mode 100644 index 00000000..aa6327e8 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/Unicorn.java @@ -0,0 +1,50 @@ +package src.main.java.org.teachingextentions.logo; + +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.ProgramWindow; +import src.main.java.org.teachingextentions.logo.Turtle.Animals; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.utils.PuzzleUtils.Tile; + +import javax.swing.*; +import java.awt.*; + +/** + * Unicorns are magical - like programming! + * The Unicorn lets you add Unicorns (rather than Turtles!) to your window + */ +public class Unicorn implements Paintable +{ + private int x; + private int y; + private Image image; + private int scale; + private Dimension dimension = new Dimension(10, 10); + public Unicorn(int x, int y, int scale) + { + this.x = x; + this.y = y; + this.scale = scale / 10; + this.image = getImage(); + } + private static Image getImage() + { + return ObjectUtils.loadImage(Tile.class, Animals.Unicorn + ".png"); + } + /** + * Adds a Unicorn to the Program Window.
+ *
Example: {@code Unicorn.addTo(programWindow)}
+ * + * @param programWindow + * the current Program Window + */ + public void addTo(ProgramWindow programWindow) + { + programWindow.add(this); + } + @Override + public void paint(Graphics2D g, JPanel caller) + { + g.drawImage(this.image, this.x, this.y, this.dimension.width * scale, this.dimension.height * scale, null); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Action0.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Action0.java new file mode 100644 index 00000000..4ce77419 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Action0.java @@ -0,0 +1,5 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public interface Action0 { + public void call(); +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalApprover.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalApprover.java new file mode 100644 index 00000000..df946cca --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalApprover.java @@ -0,0 +1,11 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public interface ApprovalApprover { + boolean approve() throws Exception; + + public void cleanUpAfterSuccess(ApprovalFailureReporter reporter) throws Exception; + + void fail(); + + void reportFailure(ApprovalFailureReporter reporter) throws Exception; +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalFailureOverrider.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalFailureOverrider.java new file mode 100644 index 00000000..598d1c94 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalFailureOverrider.java @@ -0,0 +1,5 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public interface ApprovalFailureOverrider extends ApprovalFailureReporter { + public boolean askToChangeReceivedToApproved(String received, String approved) throws Exception; +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalFailureReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalFailureReporter.java new file mode 100644 index 00000000..13567ef2 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalFailureReporter.java @@ -0,0 +1,5 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public interface ApprovalFailureReporter { + public void report(String received, String approved) throws Exception; +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalNamer.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalNamer.java new file mode 100644 index 00000000..c8c4fec2 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalNamer.java @@ -0,0 +1,7 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public interface ApprovalNamer { + String getApprovalName(); + + String getSourceFilePath(); +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalReporterWithCleanUp.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalReporterWithCleanUp.java new file mode 100644 index 00000000..ba474562 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalReporterWithCleanUp.java @@ -0,0 +1,7 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public interface ApprovalReporterWithCleanUp { + public void cleanUp(String received, String approved) throws Exception; +} + + diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalResults.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalResults.java new file mode 100644 index 00000000..3acf832d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalResults.java @@ -0,0 +1,7 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public class ApprovalResults { + public static void UniqueForOs() { + NamerFactory.asMachineSpecificTest(new OsEnvironmentLabeller()); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalTextWriter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalTextWriter.java new file mode 100644 index 00000000..0a2c9612 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalTextWriter.java @@ -0,0 +1,32 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.io.File; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.FileUtils; + + +public class ApprovalTextWriter implements ApprovalWriter { + private final String text; + private final String fileExtensionWithoutDot; + + public ApprovalTextWriter(String text, String fileExtensionWithoutDot) { + this.text = text; + this.fileExtensionWithoutDot = fileExtensionWithoutDot; + } + + @Override + public String writeReceivedFile(String received) throws Exception { + FileUtils.writeFile(new File(received), text); + return received; + } + + @Override + public String getApprovalFilename(String base) { + return base + Writer.approved + "." + fileExtensionWithoutDot; + } + + @Override + public String getReceivedFilename(String base) { + return base + Writer.received + "." + fileExtensionWithoutDot; + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalWriter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalWriter.java new file mode 100644 index 00000000..f85ad3e1 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ApprovalWriter.java @@ -0,0 +1,10 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public interface ApprovalWriter { + public String writeReceivedFile(String received) throws Exception; + + public String getReceivedFilename(String base); + + public String getApprovalFilename(String base); +} + diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Approvals.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Approvals.java new file mode 100644 index 00000000..56cceeb9 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Approvals.java @@ -0,0 +1,136 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.awt.Component; +import java.awt.image.BufferedImage; +import java.util.Arrays; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ReporterFactory.FileTypes; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.ApprovalFailureReporter; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.FileApprover; + +/** + * Approvals allows you to unit test complex objects

+ * + * -- Create a Golden Master file (approved)
+ * -- Verify against your result file (received)
+ * -- Download BeyondCompare to view the two files
+ */ +public class Approvals +{ + /** + * Verifies the output file (received) against a Golden Master file (approved)
+ * If there is no GoldenMaster, then the test will fail + *
Example: {@code Approvals.verify(response)}
+ * + * @param response + * The string to be verified + */ + public static void verify(String response) throws Exception + { + verify(new ApprovalTextWriter(response, "txt"), FileTypes.Text); + } + public static void verifyAll(String header, T[] values) + { + Approvals.verifyAll(header, Arrays.asList(values)); + } + public static void verifyAll(String header, Iterable values) + { + Approvals.verifyAll(header, values, new Function1() + { + @Override + public String call(T i) + { + return i + ""; + } + }); + } + public static void verifyAll(String header, T[] values, Function1 f1) + { + verifyAll(header, Arrays.asList(values), f1); + } + public static void verifyAll(String header, Iterable array, Function1 f1) + { + String text = formatHeader(header) + ArrayUtils.toString(array, f1); + verify(new ApprovalTextWriter(text, "txt"), FileTypes.Text); + } + private static String formatHeader(String header) + { + return StringUtils.isEmpty(header) ? "" : header + "\r\n\r\n\r\n"; + } + public static void verifyHtml(String response) throws Exception + { + verify(new ApprovalTextWriter(response, "html"), FileTypes.Html); + } + /** + * Verifies the output file (received) against a Golden Master file (approved)
+ * If there is no GoldenMaster, then the test will fail + *
Example: {@code Approvals.verify(component)}
+ * + * @param component + * The component to be verified + */ + public static void verify(Component component) + { + Approvals.verify(new ComponentApprovalWriter(component), FileTypes.Image); + } + public static void verify(BufferedImage bufferedImage) + { + verify(new ImageApprovalWriter(bufferedImage), FileTypes.Image); + } + public static void verify(ApprovalWriter writer, ApprovalNamer namer, + src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalFailureReporter approvalFailureReporter) { + // verify(new FileApprover(writer, namer), approvalFailureReporter); + } + public static void verify(ApprovalWriter writer, String fileType) + { + verify(writer, createApprovalNamer(), ReporterFactory.get(fileType)); + } + public static void verify(FileApprover approver, ApprovalFailureReporter reporter) + { + try + { + if (!approver.approve()) + { + boolean passed = false; + if (reporter instanceof ApprovalFailureReporter) + { + passed = approver.askToChangeReceivedToApproved((ApprovalFailureOverrider) reporter); + } + if (!passed) + { + approver.reportFailure(reporter); + approver.fail(); + } + else + { + approver.cleanUpAfterSuccess(reporter); + } + } + else + { + approver.cleanUpAfterSuccess(reporter); + } + } + catch (Exception e) + { + throw ObjectUtils.throwAsError(e); + } + } + public static ApprovalNamer createApprovalNamer() + { + return new JUnitStackTraceNamer(); + } + /** + * Verifies the output file (received) against a Golden Master file (approved)
+ * If there is no GoldenMaster, then the test will fail + *
Example: {@code Approvals.verify(object)}
+ * + * @param response + * The object to be verified
+ * NOTE: the object will be returned as a String + */ + public static void verify(Object o) throws Exception + { + Approvals.verify(o + ""); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ArrayUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ArrayUtils.java new file mode 100644 index 00000000..f5fd20c1 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ArrayUtils.java @@ -0,0 +1,77 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * A static class of convenience methods for arrays and collections. + */ +public class ArrayUtils { + public static java.util.Collection addArray(java.util.Collection v, T array[]) { + if ((array == null) || (v == null)) { + return v; + } + Collections.addAll(v, array); + return v; + } + + public static String toString(T[] values, Function1 formatter) { + return toString(Arrays.asList(values), formatter); + } + + public static String toString(Iterable values, Function1 formatter) { + StringBuilder b = new StringBuilder(); + for (T t : values) { + b.append(formatter.call(t)).append("\r\n"); + } + return b.toString(); + } + + public static T[] toReverseArray(T[] array) { + for (int i = 0; i < array.length / 2; i++) { + T o1 = array[i]; + int end = array.length - i - 1; + T o2 = array[end]; + array[i] = o2; + array[end] = o1; + } + return array; + } + + public static boolean isEmpty(Object[] array) { + return ((array == null) || (array.length == 0)); + } + + public static T getFirst(T[] array, Comparator comparator) { + return get(array, comparator, true); + } + + private static T get(T[] array, Comparator sorter, boolean wantFirst) { + if (isEmpty(array)) { + return null; + } + T last = array[0]; + for (int i = 1; i < array.length; i++) { + int compare = sorter.compare(last, array[i]); + if ((wantFirst && compare > 0) || (!wantFirst && compare < 0)) { + last = array[i]; + } + } + return last; + } + + public static T getLast(List list) { + return list.get(list.size() - 1); + } + + public static List combine(List list1, List list2) { + List all = new ArrayList<>(); + all.addAll(list1); + all.addAll(list2); + return all; + } + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Asserts.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Asserts.java new file mode 100644 index 00000000..4a5a91fb --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Asserts.java @@ -0,0 +1,19 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public class Asserts { + + public static T assertNotNull(String label, T o) { + if (o == null) { + throw new NullPointerException(label + " was null"); + } + return o; + } + + public static void equals(String label, double expected, double actual, double precision) { + if (!NumberUtils.equals(expected, actual, precision)) { + throw new IllegalStateException(label + " " + + expected + "!=" + actual); + } + } + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ClassUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ClassUtils.java new file mode 100644 index 00000000..98ba98cb --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ClassUtils.java @@ -0,0 +1,84 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ClassUtils { + + public static Class getWrapperClass(Class primitiveType) { + if (boolean.class.equals(primitiveType)) { + return Boolean.class; + } else if (float.class.equals(primitiveType)) { + return Float.class; + } else if (long.class.equals(primitiveType)) { + return Long.class; + } else if (int.class.equals(primitiveType)) { + return Integer.class; + } else if (short.class.equals(primitiveType)) { + return Short.class; + } else if (byte.class.equals(primitiveType)) { + return Byte.class; + } else if (double.class.equals(primitiveType)) { + return Double.class; + } else if (char.class.equals(primitiveType)) { + return Character.class; + } else { + return primitiveType; + } + } + + public static boolean hasMethod(Class clazz, String methodName, Class... parameterTypes) { + try { + return clazz.getMethod(methodName, parameterTypes) != null; + } catch (SecurityException e) { + throw ObjectUtils.throwAsError(e); + } catch (NoSuchMethodException e) { + return false; + } + } + + public static File getSourceDirectory(Class clazz) { + final String name = clazz.getName(); + String[] split = name.split("\\."); + split[split.length - 1] = split[split.length - 1] + ".java"; + File found = find(new File("."), Arrays.asList(split)); + if (found == null) { + throw new FormattedException("Didn't find %s under %s", name, new File(".")); + } + return found.getParentFile(); + } + + public static File find(File file, List matches) { + ArrayList copy = new ArrayList<>(); + copy.addAll(matches); + copy.add(0, "*"); + return find2(file, copy); + } + + public static File find2(File file, List matches) { + SearchingFileFilter searchingFileFilter = new SearchingFileFilter(matches); + File[] listFiles = file.listFiles(searchingFileFilter); + for (File file2 : listFiles) { + if (file2.isDirectory()) { + File found = find2(file2, searchingFileFilter.getSubset(file2.getName())); + if (found != null) { + return found; + } + } else { + return file2; + } + } + return null; + } + + public static T create(Class clazz) { + try { + return clazz.newInstance(); + } catch (Exception e) { + throw ObjectUtils.throwAsError(e); + } + } + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ComponentApprovalWriter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ComponentApprovalWriter.java new file mode 100644 index 00000000..09ebad81 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ComponentApprovalWriter.java @@ -0,0 +1,50 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; + +public class ComponentApprovalWriter implements ApprovalWriter { + private ImageApprovalWriter image = null; + + public ComponentApprovalWriter(Component c) { + BufferedImage image = drawComponent(c); + this.image = new ImageApprovalWriter(image); + } + + public static BufferedImage drawComponent(Component c) { + validateComponent(c); + BufferedImage image = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics g = image.createGraphics(); + c.paint(g); + g.dispose(); + return image; + } + + private static void validateComponent(Component c) { + if (!c.isValid()) { + if (c instanceof JFrame) { + ((JFrame) c).pack(); + } else { + JFrame frame = new JFrame(); + frame.getContentPane().add(c); + frame.pack(); + } + } + } + + @Override + public String writeReceivedFile(String filename) throws Exception { + return image.writeReceivedFile(filename); + } + + @Override + public String getReceivedFilename(String base) { + return image.getReceivedFilename(base); + } + + @Override + public String getApprovalFilename(String base) { + return image.getApprovalFilename(base); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/DateUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/DateUtils.java new file mode 100644 index 00000000..aad715eb --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/DateUtils.java @@ -0,0 +1,58 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +public class DateUtils { + private static int TIME_SCALE[] = {Calendar.YEAR, + Calendar.MONTH, + Calendar.DATE, + Calendar.HOUR_OF_DAY, + Calendar.HOUR, + Calendar.MINUTE, + Calendar.SECOND, + Calendar.MILLISECOND}; + + public static Calendar setSignificantDigit(Calendar calendar, int smallestUnits) { + boolean removeOn = false; + for (int i : TIME_SCALE) { + if (removeOn) { + if (i == Calendar.DATE) { + // Work around since this is broke + calendar.set(i, 1); + } else if (i == Calendar.HOUR_OF_DAY) { + // Work around since this is broke + calendar.set(i, 0); + } else { + calendar.clear(i); + } + } + if (i == smallestUnits) { + removeOn = true; + } + } + return calendar; + } + + public static void main(String args[]) { + MySystem.variable("Calendar.DATE = " + Calendar.DATE); + MySystem.variable("Year", setSignificantDigit(new GregorianCalendar(), Calendar.YEAR).getTime()); + MySystem.variable("Month", setSignificantDigit(new GregorianCalendar(), Calendar.MONTH).getTime()); + MySystem.variable("Day", setSignificantDigit(new GregorianCalendar(), Calendar.DAY_OF_MONTH).getTime()); + MySystem.variable("Hour", setSignificantDigit(new GregorianCalendar(), Calendar.HOUR).getTime()); + MySystem.variable("Minute", setSignificantDigit(new GregorianCalendar(), Calendar.MINUTE).getTime()); + MySystem.variable("End Of Day", rollToEndOfDay(new Date()).getTime()); + } + + public static GregorianCalendar rollToEndOfDay(Date date) { + GregorianCalendar gregorianCalendar = new GregorianCalendar(); + gregorianCalendar.setTime(date); + gregorianCalendar.set(Calendar.HOUR_OF_DAY, 23); + gregorianCalendar.set(Calendar.MINUTE, 59); + gregorianCalendar.set(Calendar.SECOND, 59); + gregorianCalendar.set(Calendar.MILLISECOND, 999); + return gregorianCalendar; + } + +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/FormattedException.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/FormattedException.java new file mode 100644 index 00000000..7006b21b --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/FormattedException.java @@ -0,0 +1,11 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public class FormattedException extends RuntimeException { + + private static final long serialVersionUID = -4388436150197314047L; + + public FormattedException(String string, Object... params) { + super(String.format(string, params)); + MySystem.variable(this.getMessage()); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/FrameCloser.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/FrameCloser.java new file mode 100644 index 00000000..7c7875a3 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/FrameCloser.java @@ -0,0 +1,18 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public class FrameCloser extends java.awt.event.WindowAdapter { + /** + * ******************************************************************* + */ + public void windowClosing(java.awt.event.WindowEvent e) { + e.getWindow().dispose(); + } + + /** + * ******************************************************************* + */ + public void windowClosed(java.awt.event.WindowEvent e) { + System.exit(0); + } + /***********************************************************************/ +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Function0.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Function0.java new file mode 100644 index 00000000..5b64113f --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Function0.java @@ -0,0 +1,6 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +public interface Function0 { + public Out call(); +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Function1.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Function1.java new file mode 100644 index 00000000..72aa1742 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Function1.java @@ -0,0 +1,6 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +public interface Function1 { + public Out call(In i); +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ImageApprovalWriter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ImageApprovalWriter.java new file mode 100644 index 00000000..9786e2c6 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ImageApprovalWriter.java @@ -0,0 +1,32 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.ImageIO; + +//import src.main.java.org.teachingextensions.logo.utils.ApprovalUtils.general.ApprovalWriter; + +public class ImageApprovalWriter implements ApprovalWriter { + private final BufferedImage image; + + public ImageApprovalWriter(BufferedImage image) { + this.image = image; + } + + @Override + public String writeReceivedFile(String received) throws Exception { + ImageIO.write(image, "png", new File(received)); + return received; + } + + @Override + public String getApprovalFilename(String base) { + return base + Writer.approved + ".png"; + } + + @Override + public String getReceivedFilename(String base) { + return base + Writer.received + ".png"; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/JUnitStackTraceNamer.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/JUnitStackTraceNamer.java new file mode 100644 index 00000000..c30f4637 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/JUnitStackTraceNamer.java @@ -0,0 +1,68 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.io.File; +import java.lang.reflect.Method; + +import junit.framework.TestCase; +import org.junit.Test; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.StackElementSelector; + +public class JUnitStackTraceNamer implements ApprovalNamer { + private StackTraceReflectionResult info; + + public JUnitStackTraceNamer() { + info = TestUtils.getCurrentFileForMethod(new JUnit3StackSelector()); + } + + @Override + public String getApprovalName() { + return String.format("%s.%s", info.getClassName(), info.getMethodName()); + } + + @Override + public String getSourceFilePath() { + return info.getSourceFile().getAbsolutePath() + File.separator; + } + /**************************************************************/ + /* INNER CLASSES */ + + /** + * ********************************************************** + */ + public static class JUnit3StackSelector implements StackElementSelector { + @Override + public StackTraceElement selectElement(StackTraceElement[] trace) throws Exception { + boolean inTestCase = false; + for (int i = 0; i < trace.length; i++) { + if (isTestCase(trace[i])) { + inTestCase = true; + } else if (inTestCase) { + return trace[i - 1]; + } + } + throw new RuntimeException("Could not find Junit TestCase you are running"); + } + + private boolean isTestCase(StackTraceElement element) throws ClassNotFoundException { + String fullClassName = element.getClassName(); + Class clazz = Class.forName(fullClassName); + boolean junit3 = ObjectUtils.isThisInstanceOfThat(clazz, TestCase.class); + if (!junit3) { + junit3 = isTestAttribute(clazz, element.getMethodName()); + } + return junit3; + } + + private boolean isTestAttribute(Class clazz, String methodName) throws ClassNotFoundException, SecurityException { + Method method; + try { + method = clazz.getMethod(methodName); + } catch (Throwable e) { + return false; + } + + return method.isAnnotationPresent(Test.class); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/JUnitUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/JUnitUtils.java new file mode 100644 index 00000000..28a2e2ac --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/JUnitUtils.java @@ -0,0 +1,12 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import static org.junit.Assume.assumeFalse; + +import java.awt.GraphicsEnvironment; + +public class JUnitUtils { + public static void assumeNotHeadless() { + boolean headless_check = GraphicsEnvironment.isHeadless(); + assumeFalse(headless_check); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/LambdaThreadLauncher.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/LambdaThreadLauncher.java new file mode 100644 index 00000000..47238418 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/LambdaThreadLauncher.java @@ -0,0 +1,21 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public class LambdaThreadLauncher implements Runnable { + private final Action0 function; + + public LambdaThreadLauncher(Action0 function) { + this.function = function; + new Thread(this).start(); + } + + @Override + public void run() { + try { + long delay = 0; + Thread.sleep(delay); + function.call(); + } catch (Throwable t) { + MySystem.warning("Caught throwable exception ", t); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/MySystem.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/MySystem.java new file mode 100644 index 00000000..953e1c45 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/MySystem.java @@ -0,0 +1,185 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.io.PrintWriter; +import java.util.Vector; + +public class MySystem { + public static boolean event = true; + public static boolean variable = true; + public static int hourGlass = 0; + private static long lastTime = System.currentTimeMillis(); + private static PrintWriter SYSTEM_OUT_WRITER = new PrintWriter(System.out, true); + + private static void clearHourGlass() { + if (hourGlass > 0) { + System.out.println(""); + hourGlass = 0; + } + } + + private static String getIndent() { + + return ""; + } + + private static String timeStamp() { + clearHourGlass(); + String text; + long current = System.currentTimeMillis(); + java.text.DateFormat df = java.text.DateFormat.getDateTimeInstance(); + text = "[" + df.format(new java.util.Date(current)) + " ~" + padNumber(current - lastTime) + "ms]" + + getIndent(); + lastTime = current; + return text; + } + + private static String padNumber(long number) { + String text = "" + number; + while (text.length() < 6) { + text = "0" + text; + } + return text; + } + + private static String indentMessage(String message) { + Vector v = new Vector<>(); + int place = 0; + while ((place = message.indexOf('\n', place + 1)) != -1) { + v.addElement(place); + } + if (v.size() == 0) { + // no '\n' + return message; + } + String theIndention = getIndent(); + StringBuilder buffer = new StringBuilder(message); + for (int i = (v.size() - 1); i >= 0; i--) { + int template = v.elementAt(i); + buffer.insert(template + 1, theIndention); + } + return buffer.toString(); + } + + /** + * Prints to screen any variable information to be viewed. + * + * @param statement The statement to print + */ + public synchronized static void variable(String statement) { + variable(statement, SYSTEM_OUT_WRITER); + } + + public synchronized static void variable(String statement, PrintWriter out) { + if (!variable) { + return; + } + out.println(timeStamp() + "*=>" + statement); + } + + /** + * Prints to screen any variable information to be viewed. + * + * @param name The value's name + * @param value The value to print + */ + public synchronized static void variable(String name, Object value) { + if (!variable) { + return; + } + System.out.println(timeStamp() + "*=> " + name + " = '" + (value == null ? null : value.toString()) + "'"); + } + + /** + * Prints to screen any messages to be viewed. + * + * @param Statement The statement to print + */ + public synchronized static void message(String Statement) { + System.out.println(timeStamp() + indentMessage(Statement)); + } + + /** + * Prints to screen any events to be viewed. + * + * @param Statement The statement to print + */ + public static void event(String Statement) { + if (!event) { + return; + } + System.out.println(timeStamp() + "*--" + Statement); + } + + /** + * Prints to screen any warnings to be viewed. + * + * @param statement The statement to print + */ + public synchronized static void warning(String statement) { + warning(statement, null); + } + + /** + * Prints to screen any warnings to be viewed. + * + * @param throwable The throwable to print + */ + public synchronized static void warning(Throwable throwable) { + warning(null, throwable); + } + + /** + * Prints to screen any warnings to be viewed. + * + * @param statement The statement to print + * @param throwable A throwable instance with error information + */ + public synchronized static void warning(String statement, Throwable throwable) { + warning(statement, throwable, null); + } + + public synchronized static void warning(String statement, Throwable throwable, PrintWriter out) { + clearHourGlass(); + dualPrintln("******************************************************************************************", out); + dualPrintln(timeStamp(), out); + if (statement != null) { + dualPrintln(statement, out); + } + printFullTrace(throwable, false, out); + if (throwable instanceof OutOfMemoryError) { + dumpMemory(out); + } + dualPrintln("******************************************************************************************", out); + } + + private static void dualPrintln(String string, PrintWriter out) { + System.out.println(string); + if (out != null) { + out.println(string); + } + } + + private static void printFullTrace(Throwable throwable, boolean causedBy, PrintWriter out) { + if (throwable != null) { + dualPrintln((causedBy ? "Caused by : " : "") + throwable.getMessage(), out); + throwable.printStackTrace(); + if (out != null) { + throwable.printStackTrace(out); + } + if (throwable.getCause() != null) { + printFullTrace(throwable.getCause(), true, out); + } + } + } + + public static void dumpMemory(PrintWriter out) { + System.gc(); + java.text.NumberFormat format = java.text.NumberFormat.getNumberInstance(); + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + long usedMemory = totalMemory - freeMemory; + String statement = "Memory [total, used, free] = [" + format.format(totalMemory) + " , " + + format.format(usedMemory) + " , " + format.format(freeMemory) + "]"; + variable(statement, out); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NamerFactory.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NamerFactory.java new file mode 100644 index 00000000..19e4e8dd --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NamerFactory.java @@ -0,0 +1,18 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public class NamerFactory { + private static String additionalInformation; + + public static String getAndClearAdditionalInformation() { + if (additionalInformation == null) { + return ""; + } + String out = "." + additionalInformation; + additionalInformation = null; + return out; + } + + public static void asMachineSpecificTest(Function0 environmentLabeller) { + additionalInformation = environmentLabeller.call(); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NotImplementedException.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NotImplementedException.java new file mode 100644 index 00000000..630611eb --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NotImplementedException.java @@ -0,0 +1,11 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +public class NotImplementedException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 5269165537235260411L; + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NumberUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NumberUtils.java new file mode 100644 index 00000000..65f88de3 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/NumberUtils.java @@ -0,0 +1,69 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +import java.util.Random; + +/** + * A static class of convenience functions for Manipulating numbers + */ +public class NumberUtils +{ + public static Random RANDOM = new Random(); + /** + * Loads an int from a String. + * + * @param i a string with an integer in it + * @param defaultValue value to use when no integer can be found in the string + * @return the integer found in the string + */ + public static int load(String i, int defaultValue) + { + return load(i, defaultValue, true); + } + /** + * Loads an int from a String. + * + * @param i a string with an integer in it + * @param defaultValue value to use when no integer can be found in the string + * @param stripNonNumeric true if non-numeric characters should be removed from the string + * @return the integer found in the string + */ + public static int load(String i, int defaultValue, boolean stripNonNumeric) + { + try + { + i = stripNonNumeric ? StringUtils.stripNonNumeric(i, true, true) : i; + defaultValue = Integer.parseInt(i); + } + catch (Exception ignored) + { + } + return defaultValue; + } + public static boolean equals(double one, double two, double delta) + { + double actualDelta = one - two; + return (-delta < actualDelta) && (actualDelta < delta); + } + /** + * randomly chooses a number between the minimum and maximum + *
Example: + * {@code int grade = NumberUtils.getRandomInt(1,100);}
+ * + * @param minimum The lowest possible value (inclusive) + * @param maximum The highest possible value (inclusive) + * @return the random number + */ + public static int getRandomInt(int minimum, int maximum) + { + int diff = maximum - minimum; + if (diff == 0) + { + return maximum; + } + else + { + return RANDOM.nextInt(diff) + minimum; + } + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ObjectUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ObjectUtils.java new file mode 100644 index 00000000..cfce9d5a --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ObjectUtils.java @@ -0,0 +1,55 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +import java.awt.Image; +import java.net.URL; + +import javax.swing.ImageIcon; + +/** + * A static class of convenience functions for Manipulating objects + */ +public class ObjectUtils { + + /** + * A convenience function to check if two objects are equal. + * + * @param s1 + * The first object + * @param s2 + * The second object + * @return true if Equal. + */ + public static boolean isEqual(Object s1, Object s2) { + return s1 == s2 || (s1 != null) && s1.equals(s2); + } + + public static boolean isThisInstanceOfThat(Class type, Class that) { + return that.isAssignableFrom(type); + } + + public static Error throwAsError(Throwable t) throws Error { + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else if (t instanceof Error) { + throw (Error) t; + } else { + throw new Error(t); + } + } + + public static String getClassName(Object o) { + return o == null ? "null" : o.getClass().getName(); + } + + public static Image loadImage(Class type, String name) { + URL resource = type.getResource(name); + if (resource == null) { + resource = type.getClassLoader().getResource(name); + } + if (resource == null) { + throw new IllegalStateException("Could not find image: " + name); + } + return new ImageIcon(resource).getImage(); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/OsEnvironmentLabeller.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/OsEnvironmentLabeller.java new file mode 100644 index 00000000..3840a6e0 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/OsEnvironmentLabeller.java @@ -0,0 +1,8 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public class OsEnvironmentLabeller implements Function0 { + @Override + public String call() { + return System.getProperty("os.name").replace(' ', '_'); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Query.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Query.java new file mode 100644 index 00000000..4722f138 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Query.java @@ -0,0 +1,19 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +import java.util.ArrayList; +import java.util.List; + +public class Query { + + public static List where(In[] list, Function1 predicate) { + ArrayList out = new ArrayList<>(); + for (In i : list) { + if (predicate.call(i)) { + out.add(i); + } + } + return out; + } + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ReporterFactory.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ReporterFactory.java new file mode 100644 index 00000000..0d9b1000 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ReporterFactory.java @@ -0,0 +1,93 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.*; + +public class ReporterFactory { + private static HashMap> reporters = new HashMap<>(); + + public static class FileTypes { + public static final String Text = "txt"; + public static final String Html = "html"; + public static final String Excel = "csv"; + public static final String File = "file"; + public static final String Image = "png"; + private static final String Default = "default"; + } + + static { + setupReporters(); + } + + public static ApprovalFailureReporter get(final String string) { + ApprovalFailureReporter returned = getFromAnnotation(); + returned = tryFor(returned, reporters.get(string)); + returned = tryFor(returned, reporters.get(FileTypes.Default)); + return returned; + } + + public static ApprovalFailureReporter getFromAnnotation() { + final UseReporter reporter = getAnnotationFromStackTrace(UseReporter.class); + return reporter == null ? null : getReporter(reporter); + } + + private static ApprovalFailureReporter getReporter(final UseReporter reporter) { + final Class[] classes = (Class[]) reporter + .value(); + final List reporters = new ArrayList<>(); + for (final Class clazz : classes) { + final ApprovalFailureReporter instance = ClassUtils.create(clazz); + reporters.add(instance); + } + return reporters.size() == 1 ? reporters.get(0) : (ApprovalFailureReporter) new MultiReporter(reporters); + } + + private static T getAnnotationFromStackTrace(final Class annotationClass) { + final StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + for (final StackTraceElement stack : trace) { + Method method = null; + Class clazz = null; + try { + final String methodName = stack.getMethodName(); + clazz = Class.forName(stack.getClassName()); + method = clazz.getMethod(methodName, (Class[]) null); + } catch (final Exception e) { + // ignore + } + T annotation = null; + if (method != null) { + annotation = method.getAnnotation(annotationClass); + } + if (annotation != null) { + return annotation; + } + annotation = clazz != null ? clazz.getAnnotation(annotationClass) : null; + if (annotation != null) { + return annotation; + } + } + return null; + } + + private static ApprovalFailureReporter tryFor(final ApprovalFailureReporter returned, + final Class trying) { + if (returned == null && trying != null) { + return ClassUtils.create(trying); + } + return returned; + } + + private static void setupReporters() { + reporters.put(FileTypes.Text, (Class) DiffReporter.class); + reporters.put(FileTypes.Html, (Class) DiffReporter.class); + reporters.put(FileTypes.Excel, (Class) FileLauncherReporter.class); + reporters.put(FileTypes.File, (Class) FileLauncherReporter.class); + reporters.put(FileTypes.Image, (Class) ImageReporter.class); + reporters.put(FileTypes.Default, (Class) QuietReporter.class); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Saver.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Saver.java new file mode 100644 index 00000000..f2b3fb87 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Saver.java @@ -0,0 +1,7 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +public interface Saver { + public T save(T save) throws SavingException; +} + diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SavingException.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SavingException.java new file mode 100644 index 00000000..8b4a9893 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SavingException.java @@ -0,0 +1,6 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +public class SavingException extends RuntimeException { + private static final long serialVersionUID = -2338891777546763779L; +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SearchingFileFilter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SearchingFileFilter.java new file mode 100644 index 00000000..cad32b0e --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SearchingFileFilter.java @@ -0,0 +1,48 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +import java.io.File; +import java.io.FilenameFilter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SearchingFileFilter implements FilenameFilter { + private final List matches; + + public SearchingFileFilter(List matches) { + this.matches = matches; + } + + public SearchingFileFilter(String... matches) { + ArrayList m = new ArrayList<>(); + m.addAll(Arrays.asList(matches)); + this.matches = m; + } + + public boolean accept(File dir, String name) { + boolean directory = new File(dir, name).isDirectory(); + return accept(name, directory); + } + + public boolean accept(String name, boolean directory) { + if (name.startsWith(".")) { + return false; + } + if (matches.get(0).equals("*")) { + return directory || name.equals(matches.get(1)); + } + return name.equals(matches.get(0)); + } + + public List getSubset(String file2) { + if (matches.get(0).equals("*")) { + if (matches.get(1).equals(file2)) { + return matches.subList(2, matches.size()); + } else { + return matches; + } + } + return matches.subList(1, matches.size()); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/StackTraceReflectionResult.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/StackTraceReflectionResult.java new file mode 100644 index 00000000..e166c85e --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/StackTraceReflectionResult.java @@ -0,0 +1,30 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +import java.io.File; + +public class StackTraceReflectionResult { + + private final File sourceFile; + private final String className; + private final String methodName; + + public StackTraceReflectionResult(File sourceFile, String className, String methodName) { + this.sourceFile = sourceFile; + this.className = className; + this.methodName = methodName; + } + + public File getSourceFile() { + return sourceFile; + } + + public String getClassName() { + return className; + } + + public String getMethodName() { + return methodName; + } + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/StringUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/StringUtils.java new file mode 100644 index 00000000..fdeedb7e --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/StringUtils.java @@ -0,0 +1,78 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +/** + * A static class of convenience functions for database access + */ +public final class StringUtils { + public static final String NEW_LINE = System.getProperty("line.separator"); + + private StringUtils() { + } + + public static String stripNonNumeric(String number, boolean allowDecimal, boolean allowNegative) { + boolean allowExponential = allowDecimal; + boolean afterE = false; + if (number == null) { + return ""; + } + StringBuilder result = new StringBuilder(); + for (int i = 0; i < number.length(); i++) { + char c = number.charAt(i); + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + result.append(c); + afterE = false; + break; + case '-': + if (allowNegative || afterE) { + result.append(c); + allowNegative = false; + } + break; + case '.': + if (allowDecimal) { + result.append(c); + allowDecimal = false; + } + afterE = false; + break; + case 'e': + case 'E': + if (allowExponential) { + result.append(c); + allowExponential = false; + } + afterE = true; + break; + default: + break; + } + } + return result.toString(); + } + + /** + * A convenience function to check that a String has at least 1 character. + * + * @param string + * The string in question + * @return true if Non Zero. + */ + public static boolean isNonZero(String string) { + return string != null && 0 < string.trim().length(); + } + + public static boolean isEmpty(String string) { + return !isNonZero(string); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SystemUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SystemUtils.java new file mode 100644 index 00000000..5c26c419 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/SystemUtils.java @@ -0,0 +1,11 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +import java.io.File; + +public class SystemUtils { + public static boolean isWindowsEnvironment() { + return "\\".equals(File.separator); + } + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/TestUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/TestUtils.java new file mode 100644 index 00000000..397f1d14 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/TestUtils.java @@ -0,0 +1,77 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +import java.io.File; +import java.io.IOException; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.FileUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.StackElementSelector; + + +public class TestUtils { + + public static void displayHtml(String htmlOutput) throws IOException, + InterruptedException { + displayHtml(null, ".html", htmlOutput, 3); + } + + public static void displayHtmlFile(String fileName) throws IOException { + displayFile(fileName); + } + + public static void displayHtmlFile(File file) throws IOException { + if (!file.exists()) { + return; + } + displayHtmlFile(file.getAbsolutePath()); + } + + public static void displayHtml(String outputFile, String fileExtension, String htmlOutput, int secondsTimeout) + throws IOException, InterruptedException { + File file = (outputFile == null) ? File.createTempFile("temp", fileExtension) : new File(outputFile); + FileUtils.writeFile(file, htmlOutput); + displayHtmlFile(file); + Thread.sleep(secondsTimeout * 1000); + if (outputFile == null) { + file.deleteOnExit(); + } + } + + public static void displayText(String output) throws IOException, InterruptedException { + displayHtml(null, ".txt", output, 3); + } + + public static void displayFile(String fileName) { + String cmd; + if (File.separatorChar == '\\') { + cmd = "cmd /C start \"Needed Title\" \"%s\" /B"; + } else { + cmd = "open %s"; + } + try { + cmd = String.format(cmd, fileName); + Runtime.getRuntime().exec(cmd); + Thread.sleep(2000); + } catch (Exception e) { + throw ObjectUtils.throwAsError(e); + } + } + + public static StackTraceReflectionResult getCurrentFileForMethod(StackElementSelector stackElementSelector) + throws Error { + try { + StackTraceElement trace[] = new Error().getStackTrace(); + StackTraceElement element = stackElementSelector.selectElement(trace); + return getInfo(element); + } catch (Throwable t) { + throw ObjectUtils.throwAsError(t); + } + } + + private static StackTraceReflectionResult getInfo(StackTraceElement element) throws ClassNotFoundException { + String fullClassName = element.getClassName(); + String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1); + File dir = ClassUtils.getSourceDirectory(Class.forName(fullClassName)); + return new StackTraceReflectionResult(dir, className, element.getMethodName()); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ThreadLauncher.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ThreadLauncher.java new file mode 100644 index 00000000..c7a4b776 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ThreadLauncher.java @@ -0,0 +1,31 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import java.lang.reflect.Method; + +public class ThreadLauncher implements Runnable { + private Object object = null; + private Object[] objectParams = null; + private Method method = null; + private long delay; + + public ThreadLauncher(Object object, Method method, Object[] objectParams, long delay) { + this.delay = delay; + this.object = object; + this.method = method; + this.objectParams = objectParams; + new Thread(this).start(); + } + + public void run() { + try { + Thread.sleep(delay); + method.invoke(object, objectParams); + } catch (Throwable t) { + MySystem.warning("Caught throwable exception ", t); + } + } + + public static void launch(Action0 action) { + new LambdaThreadLauncher(action); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ThreadUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ThreadUtils.java new file mode 100644 index 00000000..f186b4fd --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/ThreadUtils.java @@ -0,0 +1,12 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + + +public class ThreadUtils { + public static void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (Exception e) { + // ignore + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Tuple.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Tuple.java new file mode 100644 index 00000000..22ccd209 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Tuple.java @@ -0,0 +1,24 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public class Tuple { + private final H first; + private final K second; + + public Tuple(H first, K second) { + this.first = first; + this.second = second; + } + + public H getFirst() { + return first; + } + + public K getSecond() { + return second; + } + + @Override + public String toString() { + return String.format("<%s,%s>", first, second); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/WindowUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/WindowUtils.java new file mode 100644 index 00000000..37d53c67 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/WindowUtils.java @@ -0,0 +1,55 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; + +public class WindowUtils +{ + public static void centerWindow(java.awt.Window window) + { + Dimension d = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); + Dimension w = window.getSize(); + int dx = (int) w.getWidth(); + int dy = (int) w.getHeight(); + int x = (int) ((d.getWidth() - dx) / 2); + int y = (int) ((d.getHeight() - dy) / 2); + window.setBounds(x, y, dx, dy + 1); + } + public static void testFrame(JFrame frame) + { + testFrame(frame, true); + } + public static void copyToClipBoard(String code, boolean displayMessage) + { + java.awt.datatransfer.StringSelection selection = new java.awt.datatransfer.StringSelection(code); + java.awt.Frame frame = new java.awt.Frame(); + frame.getToolkit().getSystemClipboard().setContents(selection, selection); + if (displayMessage) + { + JOptionPane.showMessageDialog(null, "Code copied to Clipboard", "Finished", JOptionPane.INFORMATION_MESSAGE); + } + frame.dispose(); + } + public static void testFrame(JFrame frame, boolean closeOnExit) + { + if (closeOnExit) + { + testFrame(frame, new FrameCloser()); + } + else + { + testFrame(frame); + } + } + public static void testFrame(JFrame frame, WindowAdapter... array) + { + frame.pack(); + for (WindowAdapter closer : array) + { + frame.addWindowListener(closer); + } + WindowUtils.centerWindow(frame); + //frame.setVisible(true); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Writer.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Writer.java new file mode 100644 index 00000000..2dcfcd8d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/general/Writer.java @@ -0,0 +1,6 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general; + +public interface Writer { + final static String received = ".received"; + final static String approved = ".approved"; +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/FileApprover.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/FileApprover.java new file mode 100644 index 00000000..cacd6d84 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/FileApprover.java @@ -0,0 +1,71 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io; + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalApprover; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalFailureOverrider; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalFailureReporter; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalNamer; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalReporterWithCleanUp; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalWriter; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.NamerFactory; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; + +public class FileApprover implements ApprovalApprover { + private File received; + private File approved; + private final ApprovalWriter writter; + + public FileApprover(ApprovalWriter writter, ApprovalNamer namer) { + this.writter = writter; + String base = String.format("%s%s%s", namer.getSourceFilePath(), namer.getApprovalName(), + NamerFactory.getAndClearAdditionalInformation()); + received = new File(writter.getReceivedFilename(base)); + approved = new File(writter.getApprovalFilename(base)); + } + + public boolean approve() throws Exception { + received = new File(writter.writeReceivedFile(received.getAbsolutePath())); + return approveTextFile(received, approved); + } + + public void cleanUpAfterSuccess(src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.ApprovalFailureReporter reporter) throws Exception { + received.delete(); + if (reporter instanceof ApprovalReporterWithCleanUp) { + ((ApprovalReporterWithCleanUp) reporter).cleanUp(received.getAbsolutePath(), approved.getAbsolutePath()); + } + } + + public void reportFailure(src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.ApprovalFailureReporter reporter) throws Exception { + reporter.report(received.getAbsolutePath(), approved.getAbsolutePath()); + } + + public void fail() { + TestCase.assertEquals("Failed Approval", approved.getAbsolutePath(), received.getAbsolutePath()); + } + + public static boolean approveTextFile(File expected, File actual) throws IOException { + if (!expected.exists() || !actual.exists()) { + return false; + } + String t1 = FileUtils.readFile(expected); + String t2 = FileUtils.readFile(actual); + return ObjectUtils.isEqual(t1, t2); + } + + public boolean askToChangeReceivedToApproved(ApprovalFailureOverrider reporter) throws Exception { + return reporter.askToChangeReceivedToApproved(received.getAbsolutePath(), approved.getAbsolutePath()); + } + + @Override + public void cleanUpAfterSuccess(ApprovalFailureReporter reporter) throws Exception { + + } + + @Override + public void reportFailure(ApprovalFailureReporter reporter) throws Exception { + + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/FileUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/FileUtils.java new file mode 100644 index 00000000..e878060d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/FileUtils.java @@ -0,0 +1,145 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileFilter; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ArrayUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.Asserts; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; + +/** + * A static class of convenience functions for Files + */ +public class FileUtils +{ + public static String readFromClassPath(final Class clazz, final String string) + { + final InputStream resourceAsStream = loadInputStream(clazz, string); + return FileUtils.readStream(resourceAsStream); + } + public static InputStream loadInputStream(final Class type, final String name) + { + InputStream resource = type.getResourceAsStream(name); + if (resource == null) + { + resource = type.getClassLoader().getResourceAsStream(name); + } + if (resource == null) { throw new IllegalStateException("Could not find resource: " + name); } + return resource; + } + public static File[] getRecursiveFileList(final File directory) + { + return getRecursiveFileList(directory, new SimpleFileFilter()); + } + public static File[] getRecursiveFileList(final File directory, final FileFilter filter) + { + final ArrayList list = new ArrayList<>(); + if (!directory.isDirectory()) { throw new Error("File is not a directory: " + directory.getName()); } + final File directories[] = directory.listFiles(new SimpleDirectoryFilter()); + for (final File directory1 : directories) + { + ArrayUtils.addArray(list, + getRecursiveFileList(directory1, filter)); + } + final File files[] = directory.listFiles(filter); + ArrayUtils.addArray(list, files); + return list.toArray(new File[list.size()]); + } + public static void writeFile(final File file, final String text) throws IOException + { + Asserts + .assertNotNull("Writing to file: " + file, text); + final File canonicalFile = file.getCanonicalFile(); + canonicalFile.getParentFile().mkdirs(); + final BufferedWriter out = new BufferedWriter(new FileWriter(file)); + out.write(text); + out.close(); + } + public static void writeFileQuietly(final File file, final String text) + { + try + { + writeFile(file, text); + } + catch (final IOException e) + { + ObjectUtils.throwAsError(e); + } + } + public static String readFile(final String absolutePath) throws IOException + { + return readFile(new File(absolutePath)); + } + public static String readFile(final File file) throws IOException + { + final BufferedReader in = new BufferedReader(new FileReader(file)); + return readBuffer(in); + } + public static String readBuffer(final BufferedReader in) throws IOException + { + final StringBuilder string = new StringBuilder(); + while (in.ready()) + { + string.append(in.readLine()); + string.append("\n"); + } + in.close(); + return string.toString(); + } + public static String readFileWithSuppressedExceptions(final File databaseFile) + { + try + { + return FileUtils.readFile(databaseFile); + } + catch (final FileNotFoundException e) + { + throw new RuntimeException("Invalid file '" + databaseFile.getAbsolutePath() + "'", e); + } + catch (final IOException e) + { + throw new RuntimeException(e); + } + } + public static String getExtensionWithDot(final String filename) + { + final int p = filename.lastIndexOf('.'); + return filename.substring(p); + } + public static void createIfNeeded(final String file) throws IOException + { + final File f = new File(file); + if (!f.exists()) + { + writeFile(f, ""); + } + } + public static String readStream(final InputStream resourceAsStream) + { + final BufferedReader reader = new BufferedReader(new InputStreamReader(resourceAsStream)); + String resource = null; + try + { + resource = FileUtils.readBuffer(reader); + } + catch (final IOException e) + { + ObjectUtils.throwAsError(e); + } + return resource; + } + public static boolean isNonEmptyFile(final String approved) + { + final File file = new File(approved); + return file.exists() && file.length() > 0; + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/SimpleDirectoryFilter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/SimpleDirectoryFilter.java new file mode 100644 index 00000000..7aade5ed --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/SimpleDirectoryFilter.java @@ -0,0 +1,25 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io; + +import java.io.File; + +public class SimpleDirectoryFilter + implements java.io.FileFilter { + /** + * ******************************************************************** + */ + public SimpleDirectoryFilter() { + } + + /** + * ******************************************************************* + */ + + public boolean accept(File pathname) { + String name = pathname.getName().toLowerCase(); + boolean accept; + accept = !(name.equals(".") || name.equals("..")) && pathname.isDirectory(); + return accept; + } + /************************************************************************/ + /************************************************************************/ +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/SimpleFileFilter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/SimpleFileFilter.java new file mode 100644 index 00000000..862b5032 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/SimpleFileFilter.java @@ -0,0 +1,23 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io; + +import java.io.File; + +public class SimpleFileFilter implements java.io.FileFilter { + /** + * ******************************************************************** + */ + public SimpleFileFilter() { + } + + /** + * ******************************************************************* + */ + public boolean accept(File pathname) { + String name = pathname.getName().toLowerCase(); + boolean accept; + accept = !(name.equals(".") || name.equals("..")) && !pathname.isDirectory(); + return accept; + } + /************************************************************************/ + /************************************************************************/ +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/StackElementSelector.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/StackElementSelector.java new file mode 100644 index 00000000..d8cbbd4f --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/StackElementSelector.java @@ -0,0 +1,5 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io; + +public interface StackElementSelector { + public abstract StackTraceElement selectElement(StackTraceElement[] trace) throws Exception; +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/ZipUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/ZipUtils.java new file mode 100644 index 00000000..455ba6c8 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/io/ZipUtils.java @@ -0,0 +1,82 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +/** + * A static class of convenience functions for Files + */ +public class ZipUtils { + public static File zipDirectory(String directory, String zipFileName) throws IOException { + return zipDirectory(new File(directory), new File(zipFileName)); + } + + public static File zipDirectory(File directory, File zipFileName) throws IOException { + return doCreateZipFile(FileUtils.getRecursiveFileList(directory), zipFileName); + } + + public static File doCreateZipFile(File[] files, File zipFile) throws IOException { + byte[] buf = new byte[1024]; + zipFile.getParentFile().mkdirs(); + FileOutputStream fileOut = new FileOutputStream(zipFile); + ZipOutputStream out = new ZipOutputStream(fileOut); + // Compress the files + for (File file : files) { + FileInputStream in = new FileInputStream(file); + out.putNextEntry(new ZipEntry(file.getName())); + // Transfer bytes from the file to the ZIP file + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + // Complete the entry + out.closeEntry(); + in.close(); + } + // Complete the ZIP file + out.close(); + fileOut.close(); + return zipFile; + } + + public static File[] doUnzip(File destination, File zipFile) throws IOException { + ArrayList list = new ArrayList<>(); + byte[] buf = new byte[1024]; + FileInputStream fileIn = new FileInputStream(zipFile); + ZipInputStream in = new ZipInputStream(fileIn); + // DeCompress the files + ZipEntry entry = in.getNextEntry(); + while (entry != null) { + File file = new File(destination, entry.getName()); + if (entry.isDirectory()) { + file.mkdirs(); + } else { + list.add(file); + FileOutputStream out = new FileOutputStream(file); + // Transfer bytes from the file to the ZIP file + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + // Complete the entry + in.closeEntry(); + out.close(); + } + entry = in.getNextEntry(); + } + // Complete the ZIP file + in.close(); + fileIn.close(); + return list.toArray(new File[0]); + } + + public static void main(String args[]) throws IOException { + zipDirectory("c:\\t", "c:\\t\\t.zip"); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ApprovalFailureReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ApprovalFailureReporter.java new file mode 100644 index 00000000..a317f6d4 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ApprovalFailureReporter.java @@ -0,0 +1,5 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +public interface ApprovalFailureReporter { + public void report(String received, String approved) throws Exception; +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ClipboardReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ClipboardReporter.java new file mode 100644 index 00000000..89b3b18c --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ClipboardReporter.java @@ -0,0 +1,41 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import java.awt.GraphicsEnvironment; +import java.io.File; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.SystemUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.WindowUtils; + +/** + * A reporter which creates the command to accept the received + * file as the approve file and copies it to the clipboard:
+ * move received.txt approved.txt + */ +public class ClipboardReporter implements EnvironmentAwareReporter { + @Override + public void report(String received, String approved) throws Exception { + WindowUtils.copyToClipBoard(getCommandLine(received, approved), false); + } + + public static String getCommandLine(String received, String approved) { + File r = new File(received); + File a = new File(approved); + return ClipboardReporter.getAcceptApprovalText(r.getAbsolutePath(), a.getAbsolutePath()); + } + + /** + * The clipboard will not be available in a headless environment. + */ + @Override + public boolean isWorkingInThisEnvironment(String forFile) { + return !GraphicsEnvironment.isHeadless(); + } + + public static String getAcceptApprovalText(String received, String approved) { + if (SystemUtils.isWindowsEnvironment()) { + return String.format("move /Y \"%s\" \"%s\"", received, approved); + } else { + return String.format("mv %s %s", received, approved); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/DelayedClipboardReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/DelayedClipboardReporter.java new file mode 100644 index 00000000..f0d587a7 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/DelayedClipboardReporter.java @@ -0,0 +1,30 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import java.awt.GraphicsEnvironment; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.StringUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.WindowUtils; + +/** + * A reporter which creates the command to accept the received + * file as the approve file and copies it to the clipboard:
+ * move received.txt approved.txt + */ +public class DelayedClipboardReporter implements EnvironmentAwareReporter { + private static StringBuffer text = new StringBuffer(); + + @Override + public void report(String received, String approved) throws Exception { + String commandLine = ClipboardReporter.getCommandLine(received, approved); + text.append(commandLine).append(StringUtils.NEW_LINE); + WindowUtils.copyToClipBoard(text.toString(), false); + } + + /** + * The clipboard will not be available in a headless environment. + */ + @Override + public boolean isWorkingInThisEnvironment(String forFile) { + return !GraphicsEnvironment.isHeadless(); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/DiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/DiffReporter.java new file mode 100644 index 00000000..2ff74f33 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/DiffReporter.java @@ -0,0 +1,12 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx.MacDiffReporter; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows.WindowsDiffReporter; + +public class DiffReporter extends FirstWorkingReporter { + public static final DiffReporter INSTANCE = new DiffReporter(); + + public DiffReporter() { + super(WindowsDiffReporter.INSTANCE, MacDiffReporter.INSTANCE, JunitReporter.INSTANCE, QuietReporter.INSTANCE); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/EnvironmentAwareReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/EnvironmentAwareReporter.java new file mode 100644 index 00000000..1f1de4f9 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/EnvironmentAwareReporter.java @@ -0,0 +1,5 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +public interface EnvironmentAwareReporter extends ApprovalFailureReporter { + boolean isWorkingInThisEnvironment(String forFile); +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/FileLauncherReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/FileLauncherReporter.java new file mode 100644 index 00000000..54581bb0 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/FileLauncherReporter.java @@ -0,0 +1,14 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.TestUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.FileUtils; + +public class FileLauncherReporter implements ApprovalFailureReporter { + @Override + public void report(String received, String approved) throws Exception { + if (FileUtils.isNonEmptyFile(approved)) { + TestUtils.displayFile(approved); + } + TestUtils.displayFile(received); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/FirstWorkingReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/FirstWorkingReporter.java new file mode 100644 index 00000000..4125636d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/FirstWorkingReporter.java @@ -0,0 +1,29 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +public class FirstWorkingReporter implements EnvironmentAwareReporter { + private final EnvironmentAwareReporter[] reporters; + + public FirstWorkingReporter(EnvironmentAwareReporter... reporters) { + this.reporters = reporters; + } + + @Override + public void report(String received, String approved) throws Exception { + for (EnvironmentAwareReporter reporter : reporters) { + if (reporter.isWorkingInThisEnvironment(received)) { + reporter.report(received, approved); + return; + } + } + } + + @Override + public boolean isWorkingInThisEnvironment(String forFile) { + for (EnvironmentAwareReporter reporter : reporters) { + if (reporter.isWorkingInThisEnvironment(forFile)) { + return true; + } + } + return false; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/GenericDiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/GenericDiffReporter.java new file mode 100644 index 00000000..dcbc3e50 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/GenericDiffReporter.java @@ -0,0 +1,84 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ThreadUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.FileUtils; + +public class GenericDiffReporter implements EnvironmentAwareReporter { + public static final String STANDARD_ARGUMENTS = "%s %s"; + public static boolean REPORT_MISSING_FILES = false; + protected String diffProgram; + protected String arguments; + protected String diffProgramNotFoundMessage; + private List validExtensions; + public static List TEXT_FILE_EXTENSIONS = Arrays.asList(".txt", ".csv", ".htm", ".html", ".xml", + ".eml", ".java", ".css", ".js"); + public static List IMAGE_FILE_EXTENSIONS = Arrays.asList(".png", ".gif", ".jpg", ".jpeg", ".bmp", + ".tif", ".tiff"); + + public GenericDiffReporter(String diffProgram, String diffProgramNotFoundMessage) { + this(diffProgram, STANDARD_ARGUMENTS, diffProgramNotFoundMessage); + } + + private GenericDiffReporter(String diffProgram, String argumentsFormat, String diffProgramNotFoundMessage) { + this(diffProgram, argumentsFormat, diffProgramNotFoundMessage, TEXT_FILE_EXTENSIONS); + } + + public GenericDiffReporter(String diffProgram, String argumentsFormat, String diffProgramNotFoundMessage, + List validFileExtensions) { + this.diffProgram = diffProgram; + this.arguments = argumentsFormat; + this.diffProgramNotFoundMessage = diffProgramNotFoundMessage; + validExtensions = validFileExtensions; + } + + @Override + public void report(String received, String approved) throws Exception { + if (!isWorkingInThisEnvironment(received)) { + throw new RuntimeException(diffProgramNotFoundMessage); + } + FileUtils.createIfNeeded(approved); + launch(received, approved); + } + + private void launch(String received, String approved) throws IOException { + ProcessBuilder builder = new ProcessBuilder(getCommandLine(received, approved)); + builder.start(); + ThreadUtils.sleep(500); //Give program time to start + } + + public String[] getCommandLine(String received, String approved) { + String[] p = arguments.split(" "); + String r = String.format(p[0], received); + String a = String.format(p[1], approved); + String[] commands = new String[]{diffProgram, r, a}; + System.out.println(Arrays.toString(commands)); + return commands; + } + + @Override + public boolean isWorkingInThisEnvironment(String forFile) { + return checkFileExists() && isFileExtensionHandled(forFile); + } + + public boolean checkFileExists() { + boolean exists = new File(diffProgram).exists(); + if (REPORT_MISSING_FILES && !exists) { + System.out.println(String.format("%s can't find '%s'", this.getClass().getSimpleName(), diffProgram)); + } + return exists; + } + + public boolean isFileExtensionHandled(String forFile) { + return isFileExtensionValid(forFile, validExtensions); + } + + public static boolean isFileExtensionValid(String forFile, List validExtensionsWithDot) { + String extensionWithDot = FileUtils.getExtensionWithDot(forFile); + return validExtensionsWithDot.contains(extensionWithDot); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ImageReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ImageReporter.java new file mode 100644 index 00000000..53407a38 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ImageReporter.java @@ -0,0 +1,12 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx.KaleidoscopeDiffReporter; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows.BeyondCompareReporter; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows.TortoiseImageDiffReporter; + +public class ImageReporter extends FirstWorkingReporter { + public ImageReporter() { + super(TortoiseImageDiffReporter.INSTANCE, BeyondCompareReporter.INSTANCE, KaleidoscopeDiffReporter.INSTANCE, + ImageWebReporter.INSTANCE, QuietReporter.INSTANCE); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ImageWebReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ImageWebReporter.java new file mode 100644 index 00000000..08562950 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/ImageWebReporter.java @@ -0,0 +1,26 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import java.awt.GraphicsEnvironment; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.TestUtils; + +public class ImageWebReporter implements EnvironmentAwareReporter { + public static final ImageWebReporter INSTANCE = new ImageWebReporter(); + + @Override + public void report(String received, String approved) throws Exception { + String text = "
approvedreceived
%s
to approve : copy clipboard to command window
%s
"; + String moveText = ClipboardReporter.getAcceptApprovalText(received, approved); + text = String.format(text, approved, received, received, moveText); + TestUtils.displayHtml(text); + } + + /** + * We assume any environment that is not headless will have a web browser to display the image in a web page. + */ + @Override + public boolean isWorkingInThisEnvironment(String forFile) { + return !GraphicsEnvironment.isHeadless() + && GenericDiffReporter.isFileExtensionValid(forFile, GenericDiffReporter.IMAGE_FILE_EXTENSIONS); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/JunitReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/JunitReporter.java new file mode 100644 index 00000000..6b46caa4 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/JunitReporter.java @@ -0,0 +1,30 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import java.io.File; + +import junit.framework.TestCase; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.FileUtils; + +public class JunitReporter implements EnvironmentAwareReporter { + public static final JunitReporter INSTANCE = new JunitReporter(); + + @Override + public void report(String received, String approved) throws Exception { + String aText = new File(approved).exists() ? FileUtils.readFile(approved) : ""; + String rText = FileUtils.readFile(received); + String approveCommand = "To approve run : " + ClipboardReporter.getAcceptApprovalText(received, approved); + System.out.println(approveCommand); + TestCase.assertEquals(aText, rText); + } + + @Override + public boolean isWorkingInThisEnvironment(String forFile) { + try { + TestCase.assertTrue(true); + } catch (Throwable t) { + return false; + } + return GenericDiffReporter.isFileExtensionValid(forFile, GenericDiffReporter.TEXT_FILE_EXTENSIONS); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/MultiReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/MultiReporter.java new file mode 100644 index 00000000..b7358d86 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/MultiReporter.java @@ -0,0 +1,30 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class MultiReporter implements ApprovalFailureReporter { + private final Collection reporters; + + public MultiReporter(List reporters2) { + this.reporters = reporters2; + } + + @Override + public void report(String received, String approved) throws Exception { + ArrayList exceptions = new ArrayList<>(); + for (src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ApprovalFailureReporter reporter : reporters) { + try { + reporter.report(received, approved); + } catch (Throwable t) { + exceptions.add(t); + } + } + MultipleExceptions.rethrowExceptions(exceptions); + } + + public ApprovalFailureReporter[] getReporters() { + return reporters.toArray(new ApprovalFailureReporter[0]); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/MultipleExceptions.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/MultipleExceptions.java new file mode 100644 index 00000000..6f1fa891 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/MultipleExceptions.java @@ -0,0 +1,35 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import java.util.ArrayList; + +public class MultipleExceptions extends RuntimeException { + private static final long serialVersionUID = 1464454338264847972L; + + public MultipleExceptions(ArrayList exceptions) { + super(getText(exceptions), exceptions.get(0)); + } + + public static void rethrowExceptions(ArrayList exceptions) + throws Exception { + if (exceptions.size() != 0) { + if (exceptions.size() == 0) { + Throwable t = exceptions.get(0); + if (t instanceof Exception) { + throw ((Exception) t); + } + throw (Error) t; + } else { + throw new MultipleExceptions(exceptions); + } + } + } + + private static String getText(ArrayList exceptions) { + StringBuilder b = new StringBuilder("Multiple Exceptions Thrown:"); + for (int i = 0; i < exceptions.size(); i++) { + b.append(String.format("\n #%s): %s", i + 1, exceptions.get(i) + .getMessage())); + } + return b.toString(); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/QuietReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/QuietReporter.java new file mode 100644 index 00000000..7c2a37ca --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/QuietReporter.java @@ -0,0 +1,15 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +public class QuietReporter implements EnvironmentAwareReporter { + public static final QuietReporter INSTANCE = new QuietReporter(); + + @Override + public void report(String received, String approved) throws Exception { + System.out.println(ClipboardReporter.getAcceptApprovalText(received, approved)); + } + + @Override + public boolean isWorkingInThisEnvironment(String forFile) { + return true; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/UseReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/UseReporter.java new file mode 100644 index 00000000..1dd76ddc --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/UseReporter.java @@ -0,0 +1,9 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface UseReporter { + Class[] value(); +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/BeyondCompareImageReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/BeyondCompareImageReporter.java new file mode 100644 index 00000000..90933228 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/BeyondCompareImageReporter.java @@ -0,0 +1,19 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx; + +import java.text.MessageFormat; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; + +public class BeyondCompareImageReporter extends + GenericDiffReporter +{ + public static final BeyondCompareImageReporter INSTANCE = new BeyondCompareImageReporter(); + static final String DIFF_PROGRAM = "/usr/local/bin/bcompare"; + static final String MESSAGE = MessageFormat.format( + "Unable to find Beyond Compare at {0}", + DIFF_PROGRAM); + + public BeyondCompareImageReporter() { + super(DIFF_PROGRAM, STANDARD_ARGUMENTS, MESSAGE, IMAGE_FILE_EXTENSIONS); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/BeyondCompareReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/BeyondCompareReporter.java new file mode 100644 index 00000000..484284ad --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/BeyondCompareReporter.java @@ -0,0 +1,18 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx; + +import java.text.MessageFormat; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; + +public class BeyondCompareReporter extends GenericDiffReporter +{ + public static final BeyondCompareReporter INSTANCE = new BeyondCompareReporter(); + static final String DIFF_PROGRAM = "/usr/local/bin/bcompare"; + static final String MESSAGE = MessageFormat.format( + "Unable to find Beyond Compare at {0}", DIFF_PROGRAM); + public BeyondCompareReporter() + { + super(DIFF_PROGRAM, MESSAGE); + } +} + diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/DiffMergeReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/DiffMergeReporter.java new file mode 100644 index 00000000..b08f465d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/DiffMergeReporter.java @@ -0,0 +1,16 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx; + +import java.text.MessageFormat; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; + +public class DiffMergeReporter extends GenericDiffReporter { + public static final DiffMergeReporter INSTANCE = new DiffMergeReporter(); + private static final String DIFF_PROGRAM = "/Applications/DiffMerge.app/Contents/MacOS/DiffMerge"; + static final String MESSAGE = MessageFormat.format("Unable to find DiffMerge at {0}", + DIFF_PROGRAM); + + public DiffMergeReporter() { + super(DIFF_PROGRAM, GenericDiffReporter.STANDARD_ARGUMENTS, MESSAGE, GenericDiffReporter.TEXT_FILE_EXTENSIONS); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/KaleidoscopeDiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/KaleidoscopeDiffReporter.java new file mode 100644 index 00000000..426f7cdf --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/KaleidoscopeDiffReporter.java @@ -0,0 +1,22 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx; + +import java.text.MessageFormat; +import java.util.List; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ArrayUtils; + +public class KaleidoscopeDiffReporter extends GenericDiffReporter { + private static final String DIFF_PROGRAM = "/Applications/Kaleidoscope.app/Contents/MacOS/ksdiff"; + static final String MESSAGE = MessageFormat + .format("Unable to find Kaleidoscope at {0}", + DIFF_PROGRAM); + private static List fileTypes = ArrayUtils.combine( + GenericDiffReporter.IMAGE_FILE_EXTENSIONS, + GenericDiffReporter.TEXT_FILE_EXTENSIONS); + public static final KaleidoscopeDiffReporter INSTANCE = new KaleidoscopeDiffReporter(); + + public KaleidoscopeDiffReporter() { + super(DIFF_PROGRAM, GenericDiffReporter.STANDARD_ARGUMENTS, MESSAGE, fileTypes); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/MacDiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/MacDiffReporter.java new file mode 100644 index 00000000..e438b993 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/MacDiffReporter.java @@ -0,0 +1,13 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.FirstWorkingReporter; + +public class MacDiffReporter extends FirstWorkingReporter +{ + public static final MacDiffReporter INSTANCE = new MacDiffReporter(); + public MacDiffReporter() + { + super(DiffMergeReporter.INSTANCE, KaleidoscopeDiffReporter.INSTANCE, P4MergeReporter.INSTANCE, + TkDiffReporter.INSTANCE, BeyondCompareReporter.INSTANCE, BeyondCompareImageReporter.INSTANCE); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/P4MergeReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/P4MergeReporter.java new file mode 100644 index 00000000..e3ddbcd1 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/P4MergeReporter.java @@ -0,0 +1,24 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx; + +import java.text.MessageFormat; +import java.util.List; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ArrayUtils; + +public class P4MergeReporter extends GenericDiffReporter { + private static final String DIFF_PROGRAM = "/Applications/p4merge.app/Contents/MacOS/p4merge"; + public static final String MESSAGE = MessageFormat + .format( + "Unable to find P4Merge at {0}" + + "\nYou can install P4Merge " + + "at http://www.perforce.com/downloads/Perforce/20-User#10", + DIFF_PROGRAM); + private static List fileTypes = ArrayUtils.combine(GenericDiffReporter.IMAGE_FILE_EXTENSIONS, + GenericDiffReporter.TEXT_FILE_EXTENSIONS); + public static final P4MergeReporter INSTANCE = new P4MergeReporter(); + + public P4MergeReporter() { + super(DIFF_PROGRAM, GenericDiffReporter.STANDARD_ARGUMENTS, P4MergeReporter.MESSAGE, fileTypes); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/TkDiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/TkDiffReporter.java new file mode 100644 index 00000000..378c4f8e --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/macosx/TkDiffReporter.java @@ -0,0 +1,16 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.macosx; + +import java.text.MessageFormat; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; + +public class TkDiffReporter extends GenericDiffReporter { + private static final String DIFF_PROGRAM = "/Applications/TkDiff.app/Contents/MacOS/tkdiff"; + static final String MESSAGE = MessageFormat.format("Unable to find TkDiffMerge at {0}", + DIFF_PROGRAM); + public static final TkDiffReporter INSTANCE = new TkDiffReporter(); + + public TkDiffReporter() { + super(DIFF_PROGRAM, GenericDiffReporter.STANDARD_ARGUMENTS, MESSAGE, GenericDiffReporter.TEXT_FILE_EXTENSIONS); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/BeyondCompareReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/BeyondCompareReporter.java new file mode 100644 index 00000000..8803c242 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/BeyondCompareReporter.java @@ -0,0 +1,16 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows; + +import java.text.MessageFormat; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; + +public class BeyondCompareReporter extends GenericDiffReporter { + public static final BeyondCompareReporter INSTANCE = new BeyondCompareReporter(); + static final String DIFF_PROGRAM = "C:\\Program Files\\Beyond Compare 3\\BCompare.exe"; + static final String MESSAGE = MessageFormat.format( + "Unable to find Beyond Compare at {0}", DIFF_PROGRAM); + + public BeyondCompareReporter() { + super(DIFF_PROGRAM, MESSAGE); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseDiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseDiffReporter.java new file mode 100644 index 00000000..8ef1a81b --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseDiffReporter.java @@ -0,0 +1,11 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.FirstWorkingReporter; + +public class TortoiseDiffReporter extends FirstWorkingReporter { + public static final TortoiseDiffReporter INSTANCE = new TortoiseDiffReporter(); + + public TortoiseDiffReporter() { + super(TortoiseTextDiffReporter.INSTANCE, TortoiseImageDiffReporter.INSTANCE); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseImageDiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseImageDiffReporter.java new file mode 100644 index 00000000..543f3ce4 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseImageDiffReporter.java @@ -0,0 +1,12 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; + +public class TortoiseImageDiffReporter extends GenericDiffReporter { + public static final TortoiseImageDiffReporter INSTANCE = new TortoiseImageDiffReporter(); + + public TortoiseImageDiffReporter() { + super("C:\\Program Files\\TortoiseSVN\\bin\\TortoiseIDiff.exe", "/left:\"%s\" /right:\"%s\"", + TortoiseTextDiffReporter.MESSAGE, GenericDiffReporter.IMAGE_FILE_EXTENSIONS); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseTextDiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseTextDiffReporter.java new file mode 100644 index 00000000..af2cc991 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/TortoiseTextDiffReporter.java @@ -0,0 +1,20 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows; + +import java.text.MessageFormat; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; + +public class TortoiseTextDiffReporter extends GenericDiffReporter { + public static final TortoiseTextDiffReporter INSTANCE = new TortoiseTextDiffReporter(); + static final String DIFF_PROGRAM = "C:\\Program Files\\TortoiseSVN\\bin\\TortoiseMerge.exe"; + static final String MESSAGE = MessageFormat + .format( + "Unable to find TortoiseMerge at {0}" + + "\nYou can install TortoiseMerge as part " + + "of TortoiseSVN at http://tortisesvn.tigris.org", + DIFF_PROGRAM); + + public TortoiseTextDiffReporter() { + super(DIFF_PROGRAM, MESSAGE); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/WinMergeReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/WinMergeReporter.java new file mode 100644 index 00000000..d75af72d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/WinMergeReporter.java @@ -0,0 +1,17 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows; + +import java.text.MessageFormat; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.GenericDiffReporter; + +public class WinMergeReporter extends GenericDiffReporter { + public static final WinMergeReporter INSTANCE = new WinMergeReporter(); + static final String DIFF_PROGRAM = "C:\\Program Files\\WinMerge\\WinMergeU.exe"; + static final String MESSAGE = MessageFormat.format("Unable to find WinMerge at {0}" + + "\nYou can install it at http://winmerge.org/", + DIFF_PROGRAM); + + public WinMergeReporter() { + super(DIFF_PROGRAM, MESSAGE); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/WindowsDiffReporter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/WindowsDiffReporter.java new file mode 100644 index 00000000..268c2c15 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/reporters/windows/WindowsDiffReporter.java @@ -0,0 +1,11 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.windows; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.reporters.FirstWorkingReporter; + +public class WindowsDiffReporter extends FirstWorkingReporter { + public static final WindowsDiffReporter INSTANCE = new WindowsDiffReporter(); + + public WindowsDiffReporter() { + super(TortoiseDiffReporter.INSTANCE, BeyondCompareReporter.INSTANCE, WinMergeReporter.INSTANCE); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/servlets/InvokerServlet.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/servlets/InvokerServlet.java new file mode 100644 index 00000000..449e8bda --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/servlets/InvokerServlet.java @@ -0,0 +1,89 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.servlets; + +import java.io.IOException; +import java.util.HashMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.MySystem; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; + +public final class InvokerServlet extends HttpServlet +{ + private static final long serialVersionUID = 7573882633420881472L; + HashMap servlets = new HashMap<>(); + private String mask; + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + serveRequest(request, response); + } + @Override + public void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + serveRequest(request, response); + } + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + serveRequest(request, response); + } + /** + * Initialize this servlet. + */ + @Override + public void init() throws ServletException + { + mask = getServletConfig().getInitParameter("mask"); + MySystem.variable("Mask", mask); + } + @Override + public void destroy() + { + for (HttpServlet servlet : servlets.values()) + { + servlet.destroy(); + } + super.destroy(); + } + public void serveRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + String pathInfo = request.getPathInfo(); + String servletClass = pathInfo.substring(1); + int slash = servletClass.indexOf('/'); + if (slash >= 0) + { + servletClass = servletClass.substring(0, slash); + } + if (!servletClass.startsWith(mask)) + { + response.sendError(HttpServletResponse.SC_NOT_FOUND, servletClass); + return; + } + HttpServlet servlet; + synchronized (this) + { + servlet = servlets.get(servletClass); + if (servlet == null) + { + try + { + servlet = (HttpServlet) Class.forName(servletClass).newInstance(); + servlet.init(getServletConfig()); + } + catch (Throwable e) + { + ObjectUtils.throwAsError(e); + } + servlets.put(servletClass, servlet); + } + } + servlet.service(request, response); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/servlets/ValidationError.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/servlets/ValidationError.java new file mode 100644 index 00000000..d54750a2 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/servlets/ValidationError.java @@ -0,0 +1,63 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.servlets; + +import java.util.HashMap; +import java.util.HashSet; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.StringUtils; + +public class ValidationError extends RuntimeException { + private static final long serialVersionUID = 7940285202708976073L; + private HashMap errors = new HashMap<>(); + private HashSet assertions = null; + + public ValidationError(Enum enumerations[]) { + this.assertions = new HashSet<>(); + for (Enum e : enumerations) { + this.assertions.add(e.toString()); + } + } + + @Override + public String getMessage() { + return toString(); + } + + @Override + public String toString() { + return "Validation(s) failed " + errors.keySet().toString() + " - " + + errors.values().toString(); + } + + public void set(Enum assertion, boolean isOk, String errorDescription) { + setError(assertion.toString(), !isOk, errorDescription); + } + + public void setError(String assertion, boolean isError, + String errorDescription) { + if (isError && !StringUtils.isNonZero(errorDescription)) { + throw new Error("You can not use empty error descriptions"); + } + assertValidAssertion(assertion); + if (isError) { + errors.put(assertion, errorDescription); + } else { + errors.remove(assertion); + } + } + + public boolean isOk() { + return errors.size() == 0; + } + + private void assertValidAssertion(String assertion) { + if (!this.assertions.contains(assertion)) { + throw new Error("Assertion '" + assertion + "' not found from " + + assertions.toString()); + } + } + + public int size() { + return errors.size(); + } + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/ContextAware.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/ContextAware.java new file mode 100644 index 00000000..e4750784 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/ContextAware.java @@ -0,0 +1,32 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.velocity; + +import java.util.HashMap; +import java.util.Map.Entry; + +import javax.naming.Context; + +//import org.apache.velocity.context.Context; + +public interface ContextAware +{ + public void setupContext(Context context); + public static class ContextAwareMap implements ContextAware + { + HashMap add = new HashMap<>(); + public ContextAwareMap(String key, Object object) + { + put(key, object); + } + public void put(String key, Object object) + { + add.put(key, object); + } + public void setupContext(Context context) + { + for (Entry entry : add.entrySet()) + { + ((ContextAwareMap) context).put(entry.getKey(), entry.getValue()); + } + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/TestableUberspect.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/TestableUberspect.java new file mode 100644 index 00000000..2b20406a --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/TestableUberspect.java @@ -0,0 +1,265 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.velocity; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; + +import org.apache.velocity.runtime.RuntimeLogger; +import org.apache.velocity.runtime.parser.node.AbstractExecutor; +import org.apache.velocity.runtime.parser.node.BooleanPropertyExecutor; +import org.apache.velocity.runtime.parser.node.GetExecutor; +import org.apache.velocity.runtime.parser.node.PropertyExecutor; +import org.apache.velocity.util.ArrayIterator; +import org.apache.velocity.util.EnumerationIterator; +import org.apache.velocity.util.introspection.Info; +import org.apache.velocity.util.introspection.Introspector; +import org.apache.velocity.util.introspection.IntrospectorBase; +import org.apache.velocity.util.introspection.Uberspect; +import org.apache.velocity.util.introspection.UberspectLoggable; +import org.apache.velocity.util.introspection.VelMethod; +import org.apache.velocity.util.introspection.VelPropertyGet; +import org.apache.velocity.util.introspection.VelPropertySet; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; + +/** + * Implementation of Uberspect to provide the default introspective + * functionality of Velocity + * + * @author Geir Magnusson Jr. + * @version $Id: UberspectImpl.java,v 1.2.4.1 2004/03/03 23:23:08 geirm Exp $ + */ +public class TestableUberspect implements Uberspect, UberspectLoggable { + /** + * the default Velocity introspector + */ + private static IntrospectorBase introspector; + private static Introspector introspectorWithLog; + private RuntimeLogger log; + + /***********************************************************************/ + /** + * init - does nothing - we need to have setRuntimeLogger called before getting + * our introspector, as the default vel introspector depends upon it.; + */ + @Override + public void init() throws Exception { + } + + @Override + public void setRuntimeLogger(final RuntimeLogger runtimeLogger) { + introspector = new IntrospectorBase(); + introspectorWithLog = new Introspector(runtimeLogger); + log = runtimeLogger; + } + + @Override + public Iterator getIterator(final Object obj, final Info i) throws Exception { + return getStandardIterator(obj, i); + } + + public static Iterator getStandardIterator(final Object obj, final Info i) { + if (obj.getClass().isArray()) { + return new ArrayIterator(obj); + } else if (obj instanceof Collection) { + return ((Collection) obj).iterator(); + } else if (obj instanceof Map) { + return ((Map) obj).values().iterator(); + } else if (obj instanceof Iterator) { + return ((Iterator) obj); + } else if (obj instanceof Enumeration) { + return new EnumerationIterator((Enumeration) obj); + } + try { + throw new VelocityParsingError("Could not determine type of iterator in " + "#foreach loop ", i); + } catch (VelocityParsingError e) { + + e.printStackTrace(); + } + return null; + } + @Override + public VelMethod getMethod(final Object obj, final String methodName, final Object[] args, final Info i) throws Exception + { + if (obj == null) { throw new VelocityParsingError("tried " + getMethodText("null", methodName, args), i); } + final Method m = introspector.getMethod(obj.getClass(), methodName, args); + if (m == null) { throw new VelocityParsingError("Method " + + getMethodText(obj.getClass().getName(), methodName, args) + " does not exist.", i); } + return new VelMethodImpl(m); + } + public static String getMethodText(final String className, final String methodName, final Object[] args) + { + final StringBuilder methodSignature = new StringBuilder(); + for (int i = 0; args != null && i < args.length; i++) + { + methodSignature.append(ObjectUtils.getClassName(args[i])); + methodSignature.append(i == (args.length - 1) ? "" : ", "); + } + return className + "." + methodName + "(" + methodSignature + ") "; + } + @Override + public VelPropertyGet getPropertyGet(final Object obj, final String identifier, final Info i) throws Exception + { + AbstractExecutor executor; + if (obj == null) { throw new VelocityParsingError("tried " + getPropertyText("null", identifier), i); } + final Class type = obj.getClass(); + // trying getFoo() + executor = new PropertyExecutor(log, introspectorWithLog, type, identifier); + if (!executor.isAlive()) + { + // trying get("foo") + executor = new GetExecutor(log, introspectorWithLog, type, identifier); + } + if (!executor.isAlive()) + { + // trying isFoo() + executor = new BooleanPropertyExecutor(log, introspectorWithLog, type, identifier); + } + if (!executor.isAlive()) { throw new VelocityParsingError("Did not find " + + getPropertyText(obj.getClass().getName(), identifier), i); } + return new VelGetterImpl(executor); + } + private String getPropertyText(final String className, final String identifier) + { + return className + "." + identifier + " "; + } + @Override + public VelPropertySet getPropertySet(final Object obj, final String identifier, final Object arg, final Info i) throws Exception + { + final Class type = obj.getClass(); + VelMethod vm = null; + try + { + /* + * first, we introspect for the set setter method + */ + final Object[] params = {arg}; + try + { + vm = getMethod(obj, "set" + identifier, params, i); + if (vm == null) { throw new NoSuchMethodException(); } + } + catch (final NoSuchMethodException e) + { + final StringBuilder sb = new StringBuilder("set"); + sb.append(identifier); + if (Character.isLowerCase(sb.charAt(3))) + { + sb.setCharAt(3, Character.toUpperCase(sb.charAt(3))); + } + else + { + sb.setCharAt(3, Character.toLowerCase(sb.charAt(3))); + } + vm = getMethod(obj, sb.toString(), params, i); + if (vm == null) { throw new NoSuchMethodException(); } + } + } + catch (final NoSuchMethodException e) + { + /* + * right now, we only support the Map interface + */ + if (Map.class.isAssignableFrom(type)) + { + final Object[] params = {new Object(), new Object()}; + vm = getMethod(obj, "put", params, i); + if (vm != null) + return new VelSetterImpl(vm, identifier); + } + } + return (vm != null) ? new VelSetterImpl(vm) : null; + } + public static class VelMethodImpl implements VelMethod + { + Method method = null; + public VelMethodImpl(final Method m) + { + method = m; + } + @Override + public Object invoke(final Object o, final Object[] params) throws Exception + { + return method.invoke(o, params); + } + @Override + public boolean isCacheable() + { + return true; + } + @Override + public String getMethodName() + { + return method.getName(); + } + @Override + public Class getReturnType() + { + return method.getReturnType(); + } + } + public static class VelGetterImpl implements VelPropertyGet + { + AbstractExecutor ae = null; + public VelGetterImpl(final AbstractExecutor exec) + { + ae = exec; + } + @Override + public Object invoke(final Object o) throws Exception + { + return ae.execute(o); + } + @Override + public boolean isCacheable() + { + return true; + } + @Override + public String getMethodName() + { + return ae.getMethod().getName(); + } + } + public static class VelSetterImpl implements VelPropertySet + { + VelMethod vm = null; + String putKey = null; + public VelSetterImpl(final VelMethod velmethod) + { + this.vm = velmethod; + } + public VelSetterImpl(final VelMethod velmethod, final String key) + { + this.vm = velmethod; + putKey = key; + } + @Override + public Object invoke(final Object o, final Object value) throws Exception + { + final ArrayList al = new ArrayList<>(); + if (putKey != null) + { + al.add(putKey); + al.add(value); + } + else + { + al.add(value); + } + return vm.invoke(o, al.toArray()); + } + @Override + public boolean isCacheable() + { + return true; + } + @Override + public String getMethodName() + { + return vm.getMethodName(); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/VelocityParsingError.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/VelocityParsingError.java new file mode 100644 index 00000000..46ea4091 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ApprovalUtils/velocity/VelocityParsingError.java @@ -0,0 +1,17 @@ +package src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.velocity; + +import org.apache.velocity.util.introspection.Info; +public class VelocityParsingError extends Exception { + + private static final long serialVersionUID = 1L; + + public VelocityParsingError(String string, Info i) { + try { + + } + catch(Throwable t){ + + } + } + +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/ColorWheel.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/ColorWheel.java new file mode 100644 index 00000000..8a92fa96 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/ColorWheel.java @@ -0,0 +1,70 @@ +package src.main.java.org.teachingextentions.logo.utils.ColorUtils; + +import java.awt.Color; + +/** + * A painter's palette + * ColorWheel is a place to store a color palette.
+ * Example: If you have a palette of + * blue, + * red, + * and purple
+ * and then used it to print out the numbers, you would get
+ * 1 + * 2 + * 3 + * 4 + * 5 + * 6 + * 7 + * 8 + * 9 + */ +public class ColorWheel +{ + private static Wheel wheel = new Wheel<>(); + /** + * This method adds a color to the ColorWheel.
+ * Example: {@code ColorWheel.addColor(PenColors.Reds.Red);} + * @param color + * the color to add to the wheel + */ + public static void addColor(Color color) + { + wheel.add(color); + } + protected static void assertNonEmpty() + { + if (wheel.isEmpty()) + { + String message = "I call shenanigans!!!\nThis ColorWheel is empty\nYou can NOT get a color from the ColorWheel before you've added anything to it."; + throw new RuntimeException(message); + } + } + /** + * This method returns the next color of the ColorWheel.
+ * Example: {@code Color color = ColorWheel.getNextColor();} + * + * @return the next color of the ColorWheel + */ + public static Color getNextColor() + { + assertNonEmpty(); + return wheel.next(); + } + /** + * This method returns the a random color from the options on the ColorWheel.
+ * Example: {@code Color color = ColorWheel.getNextColor();} + * + * @return A random color from the ColorWheel + */ + public static Color getRandomColorFromWheel() + { + assertNonEmpty(); + return wheel.getRandomFrom(); + } + public static void removeAllColors() + { + wheel.empty(); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/PenColors.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/PenColors.java new file mode 100644 index 00000000..b0cb7c4a --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/PenColors.java @@ -0,0 +1,1557 @@ +package src.main.java.org.teachingextentions.logo.utils.ColorUtils; + +import java.awt.Color; +import java.util.Random; + +/** + * A color wheel + * Every pen color under the + * rainbow, + * and different ways to get them. + */ +public class PenColors +{ + public static class Blues + { + /** + * The color Navy + * + * + * + * + *
 
+ **/ + public static final Color Navy = Color.decode("#000080"); + /** + * The color DarkBlue + * + * + * + * + *
 
+ **/ + public static final Color DarkBlue = Color.decode("#00008B"); + /** + * The color MidnightBlue + * + * + * + * + *
 
+ **/ + public static final Color MidnightBlue = Color.decode("#191970"); + /** + * The color MediumBlue + * + * + * + * + *
 
+ **/ + public static final Color MediumBlue = Color.decode("#0000CD"); + /** + * The color Blue + * + * + * + * + *
 
+ **/ + public static final Color Blue = Color.decode("#0000FF"); + /** + * The color Teal + * + * + * + * + *
 
+ **/ + public static final Color Teal = Color.decode("#008080"); + /** + * The color DarkSlateBlue + * + * + * + * + *
 
+ **/ + public static final Color DarkSlateBlue = Color.decode("#483D8B"); + /** + * The color DarkCyan + * + * + * + * + *
 
+ **/ + public static final Color DarkCyan = Color.decode("#008B8B"); + /** + * The color SteelBlue + * + * + * + * + *
 
+ **/ + public static final Color SteelBlue = Color.decode("#4682B4"); + /** + * The color RoyalBlue + * + * + * + * + *
 
+ **/ + public static final Color RoyalBlue = Color.decode("#4169E1"); + /** + * The color SlateBlue + * + * + * + * + *
 
+ **/ + public static final Color SlateBlue = Color.decode("#6A5ACD"); + /** + * The color CadetBlue + * + * + * + * + *
 
+ **/ + public static final Color CadetBlue = Color.decode("#5F9EA0"); + /** + * The color DarkTurquoise + * + * + * + * + *
 
+ **/ + public static final Color DarkTurquoise = Color.decode("#00CED1"); + /** + * The color DodgerBlue + * + * + * + * + *
 
+ **/ + public static final Color DodgerBlue = Color.decode("#1E90FF"); + /** + * The color DeepSkyBlue + * + * + * + * + *
 
+ **/ + public static final Color DeepSkyBlue = Color.decode("#00BFFF"); + /** + * The color MediumSlateBlue + * + * + * + * + *
 
+ **/ + public static final Color MediumSlateBlue = Color.decode("#7B68EE"); + /** + * The color MediumTurquoise + * + * + * + * + *
 
+ **/ + public static final Color MediumTurquoise = Color.decode("#48D1CC"); + /** + * The color CornflowerBlue + * + * + * + * + *
 
+ **/ + public static final Color CornflowerBlue = Color.decode("#6495ED"); + /** + * The color Turquoise + * + * + * + * + *
 
+ **/ + public static final Color Turquoise = Color.decode("#40E0D0"); + /** + * The color Aqua + * + * + * + * + *
 
+ **/ + public static final Color Aqua = Color.decode("#00FFFF"); + /** + * The color Cyan + * + * + * + * + *
 
+ **/ + public static final Color Cyan = Color.decode("#00FFFF"); + /** + * The color SkyBlue + * + * + * + * + *
 
+ **/ + public static final Color SkyBlue = Color.decode("#87CEEB"); + /** + * The color LightSkyBlue + * + * + * + * + *
 
+ **/ + public static final Color LightSkyBlue = Color.decode("#87CEFA"); + /** + * The color Aquamarine + * + * + * + * + *
 
+ **/ + public static final Color Aquamarine = Color.decode("#7FFFD4"); + /** + * The color LightSteelBlue + * + * + * + * + *
 
+ **/ + public static final Color LightSteelBlue = Color.decode("#B0C4DE"); + /** + * The color LightBlue + * + * + * + * + *
 
+ **/ + public static final Color LightBlue = Color.decode("#ADD8E6"); + /** + * The color PowderBlue + * + * + * + * + *
 
+ **/ + public static final Color PowderBlue = Color.decode("#B0E0E6"); + /** + * The color PaleTurquoise + * + * + * + * + *
 
+ **/ + public static final Color PaleTurquoise = Color.decode("#AFEEEE"); + /** + * The color LightCyan + * + * + * + * + *
 
+ **/ + public static final Color LightCyan = Color.decode("#E0FFFF"); + /** + * The color AliceBlue + * + * + * + * + *
 
+ **/ + public static final Color AliceBlue = Color.decode("#F0F8FF"); + /** + * The color Azure + * + * + * + * + *
 
+ **/ + public static final Color Azure = Color.decode("#F0FFFF"); + } + public static class Browns + { + /** + * The color Maroon + * + * + * + * + *
 
+ **/ + public static final Color Maroon = Color.decode("#800000"); + /** + * The color SaddleBrown + * + * + * + * + *
 
+ **/ + public static final Color SaddleBrown = Color.decode("#8B4513"); + /** + * The color Brown + * + * + * + * + *
 
+ **/ + public static final Color Brown = Color.decode("#A52A2A"); + /** + * The color Sienna + * + * + * + * + *
 
+ **/ + public static final Color Sienna = Color.decode("#A0522D"); + /** + * The color DarkGoldenrod + * + * + * + * + *
 
+ **/ + public static final Color DarkGoldenrod = Color.decode("#B8860B"); + /** + * The color Chocolate + * + * + * + * + *
 
+ **/ + public static final Color Chocolate = Color.decode("#D2691E"); + /** + * The color Peru + * + * + * + * + *
 
+ **/ + public static final Color Peru = Color.decode("#CD853F"); + /** + * The color Goldenrod + * + * + * + * + *
 
+ **/ + public static final Color Goldenrod = Color.decode("#DAA520"); + /** + * The color RosyBrown + * + * + * + * + *
 
+ **/ + public static final Color RosyBrown = Color.decode("#BC8F8F"); + /** + * The color SandyBrown + * + * + * + * + *
 
+ **/ + public static final Color SandyBrown = Color.decode("#F4A460"); + /** + * The color Tan + * + * + * + * + *
 
+ **/ + public static final Color Tan = Color.decode("#D2B48C"); + /** + * The color BurlyWood + * + * + * + * + *
 
+ **/ + public static final Color BurlyWood = Color.decode("#DEB887"); + /** + * The color Wheat + * + * + * + * + *
 
+ **/ + public static final Color Wheat = Color.decode("#F5DEB3"); + /** + * The color NavajoWhite + * + * + * + * + *
 
+ **/ + public static final Color NavajoWhite = Color.decode("#FFDEAD"); + /** + * The color Bisque + * + * + * + * + *
 
+ **/ + public static final Color Bisque = Color.decode("#FFE4C4"); + /** + * The color BlanchedAlmond + * + * + * + * + *
 
+ **/ + public static final Color BlanchedAlmond = Color.decode("#FFEBCD"); + /** + * The color Cornsilk + * + * + * + * + *
 
+ **/ + public static final Color Cornsilk = Color.decode("#FFF8DC"); + } + public static class Grays + { + /** + * The color Black + * + * + * + * + *
 
+ **/ + public static final Color Black = Color.decode("#000000"); + /** + * The color DarkSlateGray + * + * + * + * + *
 
+ **/ + public static final Color DarkSlateGray = Color.decode("#2F4F4F"); + /** + * The color DimGray + * + * + * + * + *
 
+ **/ + public static final Color DimGray = Color.decode("#696969"); + /** + * The color Gray + * + * + * + * + *
 
+ **/ + public static final Color Gray = Color.decode("#808080"); + /** + * The color SlateGray + * + * + * + * + *
 
+ **/ + public static final Color SlateGray = Color.decode("#708090"); + /** + * The color LightSlateGray + * + * + * + * + *
 
+ **/ + public static final Color LightSlateGray = Color.decode("#778899"); + /** + * The color DarkGray + * + * + * + * + *
 
+ **/ + public static final Color DarkGray = Color.decode("#A9A9A9"); + /** + * The color Silver + * + * + * + * + *
 
+ **/ + public static final Color Silver = Color.decode("#C0C0C0"); + /** + * The color LightGray + * + * + * + * + *
 
+ **/ + public static final Color LightGray = Color.decode("#D3D3D3"); + /** + * The color Gainsboro + * + * + * + * + *
 
+ **/ + public static final Color Gainsboro = Color.decode("#DCDCDC"); + } + public static class Greens + { + /** + * The color DarkGreen + * + * + * + * + *
 
+ **/ + public static final Color DarkGreen = Color.decode("#006400"); + /** + * The color Green + * + * + * + * + *
 
+ **/ + public static final Color Green = Color.decode("#008000"); + /** + * The color ForestGreen + * + * + * + * + *
 
+ **/ + public static final Color ForestGreen = Color.decode("#228B22"); + /** + * The color DarkOliveGreen + * + * + * + * + *
 
+ **/ + public static final Color DarkOliveGreen = Color.decode("#556B2F"); + /** + * The color Lime + * + * + * + * + *
 
+ **/ + public static final Color Lime = Color.decode("#00FF00"); + /** + * The color Olive + * + * + * + * + *
 
+ **/ + public static final Color Olive = Color.decode("#808000"); + /** + * The color Teal + * + * + * + * + *
 
+ **/ + public static final Color Teal = Color.decode("#008080"); + /** + * The color SeaGreen + * + * + * + * + *
 
+ **/ + public static final Color SeaGreen = Color.decode("#2E8B57"); + /** + * The color DarkCyan + * + * + * + * + *
 
+ **/ + public static final Color DarkCyan = Color.decode("#008B8B"); + /** + * The color OliveDrab + * + * + * + * + *
 
+ **/ + public static final Color OliveDrab = Color.decode("#6B8E23"); + /** + * The color LimeGreen + * + * + * + * + *
 
+ **/ + public static final Color LimeGreen = Color.decode("#32CD32"); + /** + * The color MediumSeaGreen + * + * + * + * + *
 
+ **/ + public static final Color MediumSeaGreen = Color.decode("#3CB371"); + /** + * The color LawnGreen + * + * + * + * + *
 
+ **/ + public static final Color LawnGreen = Color.decode("#7CFC00"); + /** + * The color LightSeaGreen + * + * + * + * + *
 
+ **/ + public static final Color LightSeaGreen = Color.decode("#20B2AA"); + /** + * The color Chartreuse + * + * + * + * + *
 
+ **/ + public static final Color Chartreuse = Color.decode("#7FFF00"); + /** + * The color SpringGreen + * + * + * + * + *
 
+ **/ + public static final Color SpringGreen = Color.decode("#00FF7F"); + /** + * The color MediumSpringGreen + * + * + * + * + *
 
+ **/ + public static final Color MediumSpringGreen = Color.decode("#00FA9A"); + /** + * The color YellowGreen + * + * + * + * + *
 
+ **/ + public static final Color YellowGreen = Color.decode("#9ACD32"); + /** + * The color DarkTurquoise + * + * + * + * + *
 
+ **/ + public static final Color DarkTurquoise = Color.decode("#00CED1"); + /** + * The color DarkSeaGreen + * + * + * + * + *
 
+ **/ + public static final Color DarkSeaGreen = Color.decode("#8FBC8F"); + /** + * The color GreenYellow + * + * + * + * + *
 
+ **/ + public static final Color GreenYellow = Color.decode("#ADFF2F"); + /** + * The color MediumAquamarine + * + * + * + * + *
 
+ **/ + public static final Color MediumAquamarine = Color.decode("#66CDAA"); + /** + * The color MediumTurquoise + * + * + * + * + *
 
+ **/ + public static final Color MediumTurquoise = Color.decode("#48D1CC"); + /** + * The color Turquoise + * + * + * + * + *
 
+ **/ + public static final Color Turquoise = Color.decode("#40E0D0"); + /** + * The color LightGreen + * + * + * + * + *
 
+ **/ + public static final Color LightGreen = Color.decode("#90EE90"); + /** + * The color PaleGreen + * + * + * + * + *
 
+ **/ + public static final Color PaleGreen = Color.decode("#98FB98"); + /** + * The color Aquamarine + * + * + * + * + *
 
+ **/ + public static final Color Aquamarine = Color.decode("#7FFFD4"); + /** + * The color PaleTurquoise + * + * + * + * + *
 
+ **/ + public static final Color PaleTurquoise = Color.decode("#AFEEEE"); + } + public static class Oranges + { + /** + * The color OrangeRed + * + * + * + * + *
 
+ **/ + public static final Color OrangeRed = Color.decode("#FF4500"); + /** + * The color DarkOrange + * + * + * + * + *
 
+ **/ + public static final Color DarkOrange = Color.decode("#FF8C00"); + /** + * The color Orange + * + * + * + * + *
 
+ **/ + public static final Color Orange = Color.decode("#FFA500"); + /** + * The color Tomato + * + * + * + * + *
 
+ **/ + public static final Color Tomato = Color.decode("#FF6347"); + /** + * The color Coral + * + * + * + * + *
 
+ **/ + public static final Color Coral = Color.decode("#FF7F50"); + /** + * The color LightSalmon + * + * + * + * + *
 
+ **/ + public static final Color LightSalmon = Color.decode("#FFA07A"); + } + public static class Pinks + { + /** + * The color MediumVioletRed + * + * + * + * + *
 
+ **/ + public static final Color MediumVioletRed = Color.decode("#C71585"); + /** + * The color DeepPink + * + * + * + * + *
 
+ **/ + public static final Color DeepPink = Color.decode("#FF1493"); + /** + * The color PaleVioletRed + * + * + * + * + *
 
+ **/ + public static final Color PaleVioletRed = Color.decode("#DB7093"); + /** + * The color Fuchsia + * + * + * + * + *
 
+ **/ + public static final Color Fuchsia = Color.decode("#FF00FF"); + /** + * The color HotPink + * + * + * + * + *
 
+ **/ + public static final Color HotPink = Color.decode("#FF69B4"); + /** + * The color LightPink + * + * + * + * + *
 
+ **/ + public static final Color LightPink = Color.decode("#FFB6C1"); + /** + * The color Pink + * + * + * + * + *
 
+ **/ + public static final Color Pink = Color.decode("#FFC0CB"); + } + public static class Purples + { + /** + * The color Indigo + * + * + * + * + *
 
+ **/ + public static final Color Indigo = Color.decode("#4B0082"); + /** + * The color Purple + * + * + * + * + *
 
+ **/ + public static final Color Purple = Color.decode("#800080"); + /** + * The color DarkSlateBlue + * + * + * + * + *
 
+ **/ + public static final Color DarkSlateBlue = Color.decode("#483D8B"); + /** + * The color DarkMagenta + * + * + * + * + *
 
+ **/ + public static final Color DarkMagenta = Color.decode("#8B008B"); + /** + * The color MediumVioletRed + * + * + * + * + *
 
+ **/ + public static final Color MediumVioletRed = Color.decode("#C71585"); + /** + * The color DarkViolet + * + * + * + * + *
 
+ **/ + public static final Color DarkViolet = Color.decode("#9400D3"); + /** + * The color SlateBlue + * + * + * + * + *
 
+ **/ + public static final Color SlateBlue = Color.decode("#6A5ACD"); + /** + * The color BlueViolet + * + * + * + * + *
 
+ **/ + public static final Color BlueViolet = Color.decode("#8A2BE2"); + /** + * The color DarkOrchid + * + * + * + * + *
 
+ **/ + public static final Color DarkOrchid = Color.decode("#9932CC"); + /** + * The color MediumSlateBlue + * + * + * + * + *
 
+ **/ + public static final Color MediumSlateBlue = Color.decode("#7B68EE"); + /** + * The color RosyBrown + * + * + * + * + *
 
+ **/ + public static final Color RosyBrown = Color.decode("#BC8F8F"); + /** + * The color MediumPurple + * + * + * + * + *
 
+ **/ + public static final Color MediumPurple = Color.decode("#9370DB"); + /** + * The color PaleVioletRed + * + * + * + * + *
 
+ **/ + public static final Color PaleVioletRed = Color.decode("#DB7093"); + /** + * The color MediumOrchid + * + * + * + * + *
 
+ **/ + public static final Color MediumOrchid = Color.decode("#BA55D3"); + /** + * The color Fuchsia + * + * + * + * + *
 
+ **/ + public static final Color Fuchsia = Color.decode("#FF00FF"); + /** + * The color Magenta + * + * + * + * + *
 
+ **/ + public static final Color Magenta = Color.decode("#FF00FF"); + /** + * The color Orchid + * + * + * + * + *
 
+ **/ + public static final Color Orchid = Color.decode("#DA70D6"); + /** + * The color Plum + * + * + * + * + *
 
+ **/ + public static final Color Plum = Color.decode("#DDA0DD"); + /** + * The color Violet + * + * + * + * + *
 
+ **/ + public static final Color Violet = Color.decode("#EE82EE"); + /** + * The color Thistle + * + * + * + * + *
 
+ **/ + public static final Color Thistle = Color.decode("#D8BFD8"); + /** + * The color Lavender + * + * + * + * + *
 
+ **/ + public static final Color Lavender = Color.decode("#E6E6FA"); + } + public static class Reds + { + /** + * The color DarkRed + * + * + * + * + *
 
+ **/ + public static final Color DarkRed = Color.decode("#8B0000"); + /** + * The color FireBrick + * + * + * + * + *
 
+ **/ + public static final Color FireBrick = Color.decode("#B22222"); + /** + * The color Red + * + * + * + * + *
 
+ **/ + public static final Color Red = Color.decode("#FF0000"); + /** + * The color Crimson + * + * + * + * + *
 
+ **/ + public static final Color Crimson = Color.decode("#DC143C"); + /** + * The color OrangeRed + * + * + * + * + *
 
+ **/ + public static final Color OrangeRed = Color.decode("#FF4500"); + /** + * The color MediumVioletRed + * + * + * + * + *
 
+ **/ + public static final Color MediumVioletRed = Color.decode("#C71585"); + /** + * The color IndianRed + * + * + * + * + *
 
+ **/ + public static final Color IndianRed = Color.decode("#CD5C5C"); + /** + * The color Tomato + * + * + * + * + *
 
+ **/ + public static final Color Tomato = Color.decode("#FF6347"); + /** + * The color PaleVioletRed + * + * + * + * + *
 
+ **/ + public static final Color PaleVioletRed = Color.decode("#DB7093"); + /** + * The color Salmon + * + * + * + * + *
 
+ **/ + public static final Color Salmon = Color.decode("#FA8072"); + /** + * The color LightCoral + * + * + * + * + *
 
+ **/ + public static final Color LightCoral = Color.decode("#F08080"); + /** + * The color DarkSalmon + * + * + * + * + *
 
+ **/ + public static final Color DarkSalmon = Color.decode("#E9967A"); + /** + * The color LightSalmon + * + * + * + * + *
 
+ **/ + public static final Color LightSalmon = Color.decode("#FFA07A"); + } + public static class Whites + { + /** + * The color AntiqueWhite + * + * + * + * + *
 
+ **/ + public static final Color AntiqueWhite = Color.decode("#FAEBD7"); + /** + * The color MistyRose + * + * + * + * + *
 
+ **/ + public static final Color MistyRose = Color.decode("#FFE4E1"); + /** + * The color Beige + * + * + * + * + *
 
+ **/ + public static final Color Beige = Color.decode("#F5F5DC"); + /** + * The color Linen + * + * + * + * + *
 
+ **/ + public static final Color Linen = Color.decode("#FAF0E6"); + /** + * The color OldLace + * + * + * + * + *
 
+ **/ + public static final Color OldLace = Color.decode("#FDF5E6"); + /** + * The color Honeydew + * + * + * + * + *
 
+ **/ + public static final Color Honeydew = Color.decode("#F0FFF0"); + /** + * The color WhiteSmoke + * + * + * + * + *
 
+ **/ + public static final Color WhiteSmoke = Color.decode("#F5F5F5"); + /** + * The color Seashell + * + * + * + * + *
 
+ **/ + public static final Color Seashell = Color.decode("#FFF5EE"); + /** + * The color LavenderBlush + * + * + * + * + *
 
+ **/ + public static final Color LavenderBlush = Color.decode("#FFF0F5"); + /** + * The color AliceBlue + * + * + * + * + *
 
+ **/ + public static final Color AliceBlue = Color.decode("#F0F8FF"); + /** + * The color FloralWhite + * + * + * + * + *
 
+ **/ + public static final Color FloralWhite = Color.decode("#FFFAF0"); + /** + * The color MintCream + * + * + * + * + *
 
+ **/ + public static final Color MintCream = Color.decode("#F5FFFA"); + /** + * The color Azure + * + * + * + * + *
 
+ **/ + public static final Color Azure = Color.decode("#F0FFFF"); + /** + * The color Ivory + * + * + * + * + *
 
+ **/ + public static final Color Ivory = Color.decode("#FFFFF0"); + /** + * The color GhostWhite + * + * + * + * + *
 
+ **/ + public static final Color GhostWhite = Color.decode("#F8F8FF"); + /** + * The color Snow + * + * + * + * + *
 
+ **/ + public static final Color Snow = Color.decode("#FFFAFA"); + /** + * The color White + * + * + * + * + *
 
+ **/ + public static final Color White = Color.decode("#FFFFFF"); + } + public static class Yellows + { + /** + * The color DarkGoldenrod + * + * + * + * + *
 
+ **/ + public static final Color DarkGoldenrod = Color.decode("#B8860B"); + /** + * The color Goldenrod + * + * + * + * + *
 
+ **/ + public static final Color Goldenrod = Color.decode("#DAA520"); + /** + * The color Gold + * + * + * + * + *
 
+ **/ + public static final Color Gold = Color.decode("#FFD700"); + /** + * The color DarkKhaki + * + * + * + * + *
 
+ **/ + public static final Color DarkKhaki = Color.decode("#BDB76B"); + /** + * The color Yellow + * + * + * + * + *
 
+ **/ + public static final Color Yellow = Color.decode("#FFFF00"); + /** + * The color Khaki + * + * + * + * + *
 
+ **/ + public static final Color Khaki = Color.decode("#F0E68C"); + /** + * The color PaleGoldenrod + * + * + * + * + *
 
+ **/ + public static final Color PaleGoldenrod = Color.decode("#EEE8AA"); + /** + * The color PeachPuff + * + * + * + * + *
 
+ **/ + public static final Color PeachPuff = Color.decode("#FFDAB9"); + /** + * The color Moccasin + * + * + * + * + *
 
+ **/ + public static final Color Moccasin = Color.decode("#FFE4B5"); + /** + * The color PapayaWhip + * + * + * + * + *
 
+ **/ + public static final Color PapayaWhip = Color.decode("#FFEFD5"); + /** + * The color LemonChiffon + * + * + * + * + *
 
+ **/ + public static final Color LemonChiffon = Color.decode("#FFFACD"); + /** + * The color LightGoldenrodYellow + * + * + * + * + *
 
+ **/ + public static final Color LightGoldenrodYellow = Color.decode("#FAFAD2"); + /** + * The color LightYellow + * + * + * + * + *
 
+ **/ + public static final Color LightYellow = Color.decode("#FFFFE0"); + } + private static Random RANDOM = new Random(); + public static Color darken(Color color) + { + int red = decrease(color.getRed(), 10); + int green = decrease(color.getGreen(), 10); + int blue = decrease(color.getBlue(), 10); + return new Color(red, green, blue); + } + private static int decrease(int amount, int decreaseBy) + { + return Math.max(0, amount - decreaseBy); + } + public static Color lighten(Color color) + { + int red = increase(color.getRed(), 10); + int green = increase(color.getGreen(), 10); + int blue = increase(color.getBlue(), 10); + return new Color(red, green, blue); + } + private static int increase(int amount, int increaseBy) + { + return Math.min(255, amount + increaseBy); + } + /** + * Gets a random pen color + *
Example: {@code penColors.getRandomColor( )}
+ * @return A color + */ + public static Color getRandomColor() + { + return new Color(RANDOM.nextInt(255), RANDOM.nextInt(255), RANDOM.nextInt(255)); + } + public static void mockRandom() + { + RANDOM.setSeed(5); + } + public static int calculateTransparency(int percentTransparent) + { + int opacity = (percentTransparent * 255) / 100; + return (255 - opacity); + } + public static Color getTransparentVersion(Color color, int percentTransparency) + { + return new Color(color.getRed(), color.getGreen(), color.getBlue(), calculateTransparency(percentTransparency)); + } +} \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/Wheel.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/Wheel.java new file mode 100644 index 00000000..0a28a124 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/ColorUtils/Wheel.java @@ -0,0 +1,76 @@ +package src.main.java.org.teachingextentions.logo.utils.ColorUtils; + +import java.util.ArrayList; +import java.util.List; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.NumberUtils; + +/** + * A Wheel is a List with no ending on beginning

+ * Example:

{@code
+ *    Wheel names = new Wheel();
+ *    names.add("Chocolate");
+ *    names.add("Peanut Butter");
+ *    for(int i = 0; i < 6; i++){
+ *      String name = names.next();
+ *      System.out.print(name + " ");
+ *    }
+ * }
+ * Would result in:

+ * Chocolate Peanut Butter Chocolate Peanut Butter Chocolate Peanut Butter + * + * @param The kind of things that are in the wheel + */ +public class Wheel +{ + private final List list = new ArrayList<>(); + private int index = 0; + @SafeVarargs + public Wheel(final T... loadWith) + { + for (final T t : loadWith) + { + add(t); + } + } + public Wheel() + { + } + public void add(final T i) + { + list.add(i); + } + public T next() + { + assertNonEmpty(); + if (index >= list.size()) + { + index = 0; + } + return list.get(index++); + } + protected void assertNonEmpty() + { + if (list.isEmpty()) + { + final String message = "I call shenanigans!!!\nThis Wheel is empty\nYou can NOT get an object from the Wheel before you've added anything to it."; + throw new RuntimeException(message); + } + } + public T getRandomFrom() + { + assertNonEmpty(); + final int index = NumberUtils.getRandomInt(0, + list.size()); + return list.get(index); + } + public void empty() + { + list.clear(); + index = 0; + } + public boolean isEmpty() + { + return list.isEmpty(); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/FancyMessageBox.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/FancyMessageBox.java new file mode 100644 index 00000000..e535e49d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/FancyMessageBox.java @@ -0,0 +1,82 @@ +package src.main.java.org.teachingextentions.logo.utils.EventUtils; + +import javax.swing.ImageIcon; +import javax.swing.JOptionPane; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.NumberUtils; + +/** + * A message box
+ * Fancy MessageBox is a pop up window that you can change!
+ * Use it to collect input from the user, or to display a message for the user to read.
+ */ +public class FancyMessageBox +{ + private static FancyMessageBoxInstance fancyMessageBox = new FancyMessageBoxInstance(); + /** + * Prints a request for a numerical input to the window.
+ * Example: + * {@code int cookies = FancyMessageBox.askForNumericalInput("How many cookies would you like?", "Cookies");} + * + * @param message + * the text in the FancyMessageBox + * @param title + * the title of the FancyMessageBox + * @return the user input as a number + */ + public static int askForNumericalInput(String message, String title) + { + return fancyMessageBox.askForNumericalInput(message, title); + } + /** + * Prints a request for a text input to the window.
+ * Example: + * {@code String name = FancyMessageBox.askForTextInput("What is your nickname?", "Nicknames");} + * + * @param message + * the text in the FancyMessageBox + * @param title + * the title of the FancyMessageBox + * @return the user input as a string + */ + public static String askForTextInput(String message, String title) + { + return fancyMessageBox.askForTextInput(message, title); + } + /** + * Prints the message to the window.
+ * Example: {@code FancyMessageBox.showMessage("Girl programmers rule!","Just the Facts");} + * + * @param message + * the text in the FancyMessageBox + * @param title + * the title of the FancyMessageBox + * @param icon + * a file and path that has an image for the MessageBox + */ + public static void showMesage(String message, String title, ImageIcon icon) + { + fancyMessageBox.showMessage(message, title, icon); + } + public static class FancyMessageBoxInstance + { + public static void mock(FancyMessageBoxInstance messageBoxMock) + { + fancyMessageBox = messageBoxMock; + } + public int askForNumericalInput(String message, String title) + { + String input = askForTextInput(message, title); + return NumberUtils.load(input, 0); + } + public String askForTextInput(String message, String title) + { + return JOptionPane.showInputDialog(null, message, title, -1); + } + public void showMessage(String message, String title, ImageIcon icon) + { + JOptionPane.showMessageDialog(null, message, title, -1, icon); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/LeftClickMouseAdapter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/LeftClickMouseAdapter.java new file mode 100644 index 00000000..e33ccd05 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/LeftClickMouseAdapter.java @@ -0,0 +1,39 @@ +package src.main.java.org.teachingextentions.logo.utils.EventUtils; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.SwingUtilities; + +public class LeftClickMouseAdapter implements MouseListener +{ + private final MouseLeftClickListener listener; + public LeftClickMouseAdapter(MouseLeftClickListener listener) + { + this.listener = listener; + } + @Override + public void mouseClicked(MouseEvent e) + { + } + @Override + public void mouseEntered(MouseEvent e) + { + } + @Override + public void mouseExited(MouseEvent e) + { + } + @Override + public void mousePressed(MouseEvent e) + { + } + @Override + public void mouseReleased(MouseEvent e) + { + if (SwingUtilities.isLeftMouseButton(e)) + { + listener.onLeftMouseClick(e.getX(), e.getY()); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MessageBox.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MessageBox.java new file mode 100644 index 00000000..9820dcc0 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MessageBox.java @@ -0,0 +1,74 @@ +package src.main.java.org.teachingextentions.logo.utils.EventUtils; + +import javax.swing.JOptionPane; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.NumberUtils; + +/** + * A message box
+ * MessageBox is a pop up window. Use it to collect input from the user, or to display a message for the user to read.
+ */ +public class MessageBox +{ + private static MessageBoxInstance messageBox = new MessageBoxInstance(); + /** + * Prints a request for a numerical input to the window.
+ * Example: + * {@code int cookies = MessageBox.askForNumericalInput("How many cookies would you like?");} + * + * @param message + * the text to be displayed + * @return the user input + */ + public static int askForNumericalInput(String message) + { + return messageBox.askForNumericalInput(message); + } + /** + * Prints a request for a text input to the window.
+ * Example: + * {@code String name = MessageBox.askForTextInput("What is your nickname?");} + * + * @param message + * the text to be displayed + * @return the user input + */ + public static String askForTextInput(String message) + { + return messageBox.askForTextInput(message); + } + /** + * Prints the message to the window.
+ * Example: {@code MessageBox.showMessage("Girl programmers rule!");} + * + * @param message + * the text to be displayed + * @param title + */ + public static void showMessage(String message) + { + messageBox.showMessage(message); + } + public static void mock(MessageBoxInstance messageBoxMock) + { + messageBox = messageBoxMock; + } + public static class MessageBoxInstance + { + public int askForNumericalInput(String message) + { + String input = askForTextInput(message); + return NumberUtils.load(input, 0); + } + public String askForTextInput(String message) + { + return JOptionPane.showInputDialog(message); + } + public void showMessage(String message) + { + JOptionPane.showMessageDialog(null, message); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MouseLeftClickListener.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MouseLeftClickListener.java new file mode 100644 index 00000000..39aaa91b --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MouseLeftClickListener.java @@ -0,0 +1,6 @@ +package src.main.java.org.teachingextentions.logo.utils.EventUtils; + +public interface MouseLeftClickListener +{ + void onLeftMouseClick(int x, int y); +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MouseRightClickListener.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MouseRightClickListener.java new file mode 100644 index 00000000..004f5882 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/MouseRightClickListener.java @@ -0,0 +1,6 @@ +package src.main.java.org.teachingextentions.logo.utils.EventUtils; + +public interface MouseRightClickListener +{ + void onRightMouseClick(int x, int y); +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/RightClickMouseAdapter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/RightClickMouseAdapter.java new file mode 100644 index 00000000..072ba49b --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/EventUtils/RightClickMouseAdapter.java @@ -0,0 +1,39 @@ +package src.main.java.org.teachingextentions.logo.utils.EventUtils; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.SwingUtilities; + +public class RightClickMouseAdapter implements MouseListener +{ + private final MouseRightClickListener listener; + public RightClickMouseAdapter(MouseRightClickListener listener) + { + this.listener = listener; + } + @Override + public void mouseClicked(MouseEvent e) + { + } + @Override + public void mouseEntered(MouseEvent e) + { + } + @Override + public void mouseExited(MouseEvent e) + { + } + @Override + public void mousePressed(MouseEvent e) + { + } + @Override + public void mouseReleased(MouseEvent e) + { + if (SwingUtilities.isRightMouseButton(e)) + { + listener.onRightMouseClick(e.getX(), e.getY()); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/CanvasPanel.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/CanvasPanel.java new file mode 100644 index 00000000..8f08d4ed --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/CanvasPanel.java @@ -0,0 +1,71 @@ +package src.main.java.org.teachingextentions.logo.utils.InterfaceUtils; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.util.ArrayList; + +import javax.swing.JPanel; + +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.ImageBackground; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; + +@SuppressWarnings("serial") +public class CanvasPanel extends JPanel +{ + private final ArrayList painters = new ArrayList(); + private static Graphics2D configureGraphics2D(Graphics g) + { + Graphics2D g2d = (Graphics2D) g.create(); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); + return g2d; + } + @Override + public void paint(Graphics g) + { + super.paint(g); + Graphics2D g2d = configureGraphics2D(g); + for (Paintable p : this.getPainters()) + { + p.paint(g2d, this); + } + } + public CanvasPanel remove(Paintable painter) + { + if (this.painters.contains(painter)) + { + this.painters.remove(painter); + } + return this; + } + public CanvasPanel add(Paintable painter) + { + if (!this.painters.contains(painter)) + { + this.painters.add(painter); + } + this.repaint(); + return this; + } + public CanvasPanel clear() + { + this.painters.clear(); + return this; + } + public ArrayList getPainters() + { + return new ArrayList<>(this.painters); + } + public void setBackground( + ImageBackground imageBackground) + { + if (this.painters.contains(imageBackground)) + { + this.painters.remove(imageBackground); + } + return; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/MultiTurtlePainter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/MultiTurtlePainter.java new file mode 100644 index 00000000..ba5ce75d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/MultiTurtlePainter.java @@ -0,0 +1,48 @@ +package src.main.java.org.teachingextentions.logo.utils.InterfaceUtils; + +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.util.List; + +public class MultiTurtlePainter implements Paintable { + private final List turtles; + private final Image image; + + public MultiTurtlePainter(List turtles, Image image) { + this.turtles = turtles; + this.image = image; + } + + @Override + public void paint(Graphics2D g, JPanel caller) { + if (this.turtles == null){ + return; + } + + for (Turtle turtle : turtles) + { + if (turtle.isHidden()) + { + continue; + } + Image image = getImage(); + int xCenter = image.getWidth(null) / 2; + int yCenter = image.getHeight(null) / 2; + int x = turtle.getX() - xCenter; + int y = turtle.getY() - yCenter; + AffineTransform rotate = AffineTransform.getRotateInstance(Math.toRadians(turtle.getHeadingInDegrees()), + xCenter, yCenter); + AffineTransform move = AffineTransform.getTranslateInstance(x, y); + move.concatenate(rotate); + g.drawImage(image, move, null); + } + } + + public Image getImage() { + return image; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/MultiTurtleTrailPainter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/MultiTurtleTrailPainter.java new file mode 100644 index 00000000..4bf8e1e5 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/MultiTurtleTrailPainter.java @@ -0,0 +1,37 @@ +package src.main.java.org.teachingextentions.logo.utils.InterfaceUtils; + +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.LineSegment; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.Line2D; +import java.util.List; + +public class MultiTurtleTrailPainter implements Paintable { + private final List turtles; + + public MultiTurtleTrailPainter(List turtles) { + this.turtles = turtles; + } + + @Override + public void paint(Graphics2D g, JPanel caller) { + if (turtles == null) { return; } + + for (Turtle turtle : turtles) + { + paintTrail(turtle.getTrail(), g); + } + } + + private void paintTrail(final LineSegment[] trail, Graphics2D g) { + for (LineSegment l : trail) { + g.setColor(PenColors.Yellows.Gold); + g.setStroke(new BasicStroke(l.getWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); + g.draw(new Line2D.Double(l.getStart().x, l.getStart().y, l.getEnd().x, l.getEnd().y)); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TkpPanel.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TkpPanel.java new file mode 100644 index 00000000..ebfe6dce --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TkpPanel.java @@ -0,0 +1,92 @@ +package src.main.java.org.teachingextentions.logo.utils.InterfaceUtils; + +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; + +@Deprecated +public class TkpPanel { + + private LazyPanel panel = new LazyPanel(); + + public static Graphics2D configureGraphics2D(Graphics g) { + Graphics2D g2d = (Graphics2D) g.create(); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); + return g2d; + } + + public TkpPanel add(Component component) { + this.panel.getValue().add(component); + return this; + } + + public TkpPanel setBackground(Color color) { + this.panel.getValue().setBackground(color); + return this; + } + + public TkpPanel remove(Paintable item) { + this.panel.getValue().remove(item); + return this; + } + + public TkpPanel add(Paintable item) { + this.panel.getValue().add(item); + + return this; + } + + public TkpPanel addTo(JFrame frame) { + frame.getContentPane().add(this.panel.getValue()); + return this; + } + + private class LazyPanel { + + private PaintablePanel value; + + public PaintablePanel getValue() { + if (this.value == null) { + this.value = new PaintablePanel(); + } + + return this.value; + } + + + } + + private class PaintablePanel extends JPanel { + public ArrayList interfaceElements = new ArrayList<>(); + + public PaintablePanel remove(Paintable item) { + if (interfaceElements.contains(item)) { + interfaceElements.remove(item); + } + + return this; + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = TkpPanel.configureGraphics2D(g); + for (Paintable p : interfaceElements) { + p.paint(g2d, this); + } + g2d.dispose(); + } + + protected PaintablePanel add(Paintable item) { + if (!interfaceElements.contains(item)) { + interfaceElements.add(item); + } + return this; + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtleFrame.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtleFrame.java new file mode 100644 index 00000000..8a5d5964 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtleFrame.java @@ -0,0 +1,75 @@ +package src.main.java.org.teachingextentions.logo.utils.InterfaceUtils; + +import javax.swing.JComponent; +import javax.swing.JFrame; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.FrameCloser; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.WindowUtils; +import src.main.java.org.teachingextentions.logo.utils.VirtualProctorUtils.VirtualProctorWeb; + +public class TurtleFrame +{ + public static final String TITLE = "TKPJava Turtle"; + private LazyFrame frame; + private String title; + public TurtleFrame(JFrame frame) + { + if (frame == null) { throw new IllegalArgumentException( + "frame must not be null when creating a TurtleFrame"); } + this.frame = new LazyFrame(frame); + } + public TurtleFrame(String title) + { + if (title == null) + { + title = TITLE; + } + this.frame = new LazyFrame(title); + } + public TurtleFrame() + { + this(TITLE); + } + public static void createStandardFrame(JFrame frame) + { + WindowUtils.testFrame(frame, new VirtualProctorWeb(), new FrameCloser()); + } + public TurtleFrame addContent(JComponent panel) + { + this.frame.getValue().getContentPane().add(panel); + return this; + } + public TurtleFrame setVisible(boolean visible) + { + this.frame.getValue().setVisible(visible); + return this; + } + public TurtleFrame setStandardLayout() + { + createStandardFrame(this.frame.getValue()); + return this; + } + private class LazyFrame + { + private String title; + private JFrame frame; + public LazyFrame(String title) + { + if (title == null) { throw new IllegalArgumentException( + "title must not be null when creating a LazyFrame"); } + this.title = title; + } + public LazyFrame(JFrame frame) + { + this.frame = frame; + } + public JFrame getValue() + { + if (this.frame == null) + { + this.frame = new JFrame(this.title); + } + return this.frame; + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtlePainter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtlePainter.java new file mode 100644 index 00000000..902150c8 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtlePainter.java @@ -0,0 +1,40 @@ +package src.main.java.org.teachingextentions.logo.utils.InterfaceUtils; + +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.AffineTransform; + +public class TurtlePainter implements Paintable { + private final Turtle turtle; + private final Image image; + + public TurtlePainter(Turtle turtle, Image image) { + + this.turtle = turtle; + this.image = image; + } + + @Override + public void paint(Graphics2D g, JPanel caller) { + if (turtle == null || turtle.isHidden()) { + return; + } + Image image = getImage(); + int xCenter = image.getWidth(null) / 2; + int yCenter = image.getHeight(null) / 2; + int x = turtle.getX() - xCenter; + int y = turtle.getY() - yCenter; + AffineTransform rotate = AffineTransform.getRotateInstance(Math.toRadians(turtle.getHeadingInDegrees()), + xCenter, yCenter); + AffineTransform move = AffineTransform.getTranslateInstance(x, y); + move.concatenate(rotate); + g.drawImage(image, move, null); + } + + public Image getImage() { + return image; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtleTrailPainter.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtleTrailPainter.java new file mode 100644 index 00000000..1ce02ccd --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/InterfaceUtils/TurtleTrailPainter.java @@ -0,0 +1,36 @@ +package src.main.java.org.teachingextentions.logo.utils.InterfaceUtils; + +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.LineSegment; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.Line2D; + +public class TurtleTrailPainter implements Paintable { + private final Turtle turtle; + + public TurtleTrailPainter(Turtle turtle) { + + this.turtle = turtle; + } + + @Override + public void paint(Graphics2D g, JPanel caller) { + if (turtle == null) { + return; + } + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); + for (LineSegment l : turtle.getTrail()) { + if (l != null) { + g.setColor(l.getColor()); + g.setStroke(new BasicStroke(l.getWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); + g.draw(new Line2D.Double(l.getStart().x, l.getStart().y, l.getEnd().x, l.getEnd().y)); + } + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/AngleCalculator.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/AngleCalculator.java new file mode 100644 index 00000000..d6cb4ae1 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/AngleCalculator.java @@ -0,0 +1,26 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +public class AngleCalculator { + + private final int x1; + private final int y1; + private final int x2; + private final int y2; + + public AngleCalculator(int x1, int y1, int x2, int y2) { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + } + + public double getDegreesWith0North(){ + int delta_x = this.x1 - this.x2; + int delta_y = this.y1 - this.y2; + double theta_radians = Math.atan2(delta_y, delta_x); + double degrees = Math.toDegrees(theta_radians); + return degrees - 90; + } + +} + diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Circle.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Circle.java new file mode 100644 index 00000000..db47975d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Circle.java @@ -0,0 +1,94 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.ProgramWindow; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; + +import javax.swing.*; +import java.awt.*; + +/** + * A blue circle + * The Circle allows you to draw circles on the window + */ +public class Circle implements Paintable +{ + private final int radius; + private final Color mainColor; + private int x; + private int y; + private int percentTransparent; + public Circle(int radius, Color color) + { + this.radius = radius; + this.mainColor = color; + } + /** + * Sets the center the circle + *

Example: {@code circle.setCenter(8,10)}
+ * + * @param x + * The x value + * @param y + * The y value + */ + public void setCenter(int x, int y) + { + this.x = x; + this.y = y; + } + public int getRadius() + { + return this.radius; + } + /** + * Adds a circle to the window + *
Example: {@code circle.addTo(panel)}
+ * + * @param panel + * the ProgramWindow or panel + */ + public void addTo(ProgramWindow panel) + { + panel.getCanvas().add(this); + } + /** + * Paints a circle + *
Example: {@code circle.paint(g,caller)}
+ * + * @param g + * the graphics object + * @param caller + * the Program Window or panel + */ + @Override + public void paint(Graphics2D g, JPanel caller) + { + Color color2 = PenColors.getTransparentVersion(mainColor, + percentTransparent); + g.setColor(color2); + g.fillOval(x - radius, y - radius, radius * 2, radius * 2); + } + /** + * Sets the transparency of the circle + *
Example: {@code circle.setTransparency(80)}
+ * + * @param percentTransparent + * The percentage of transparency of the circle + */ + public void setTransparency(int percentTransparent) + { + this.percentTransparent = percentTransparent; + } + public void removeFrom(ProgramWindow panel) + { + panel.remove(this); + } + public int getX() + { + return this.x; + } + public int getY() + { + return this.y; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/CompositeStroke.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/CompositeStroke.java new file mode 100644 index 00000000..205c534a --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/CompositeStroke.java @@ -0,0 +1,19 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +import java.awt.Shape; +import java.awt.Stroke; + +public class CompositeStroke implements Stroke +{ + private Stroke stroke1, stroke2; + public CompositeStroke(Stroke stroke1, Stroke stroke2) + { + this.stroke1 = stroke1; + this.stroke2 = stroke2; + } + @Override + public Shape createStrokedShape(Shape shape) + { + return stroke2.createStrokedShape(stroke1.createStrokedShape(shape)); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/DeltaCalculator.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/DeltaCalculator.java new file mode 100644 index 00000000..13207e14 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/DeltaCalculator.java @@ -0,0 +1,19 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +public class DeltaCalculator { + private final double angleInDegrees; + private final double size; + + public DeltaCalculator(double angleInDegrees, double size) { + this.angleInDegrees = angleInDegrees; + this.size = size; + } + + public double getX() { + return this.size * Math.sin(Math.toRadians(this.angleInDegrees)); + } + + public double getY() { + return -this.size * Math.cos(Math.toRadians(this.angleInDegrees)); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Diamond.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Diamond.java new file mode 100644 index 00000000..3c4c9c67 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Diamond.java @@ -0,0 +1,97 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +import java.awt.Color; +import java.awt.Graphics2D; + +import javax.swing.JPanel; + +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.ProgramWindow; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; + +/** + * The Diamond allows you to draw diamonds on the window + */ +public class Diamond implements Paintable +{ + private final int radius; + private final Color mainColor; + private int x; + private int y; + private int percentTransparent; + public Diamond(int radius, Color color) + { + this.radius = radius; + this.mainColor = color; + } + /** + * Sets the corners of the diamond + *
Example: {@code diamond.setCorners(8,10)}
+ * + * @param x + * The x value + * @param y + * The y value + */ + public void setCorners(int x, int y) + { + this.x = x; + this.y = y; + } + public int getRadius() + { + return this.radius; + } + /** + * Adds a diamond to the window + *
Example: {@code diamond.addTo(panel)}
+ * + * @param panel + * the ProgramWindow or panel + */ + public void addTo(ProgramWindow panel) + { + panel.getCanvas().add(this); + } + /** + * Paints a diamond + *
Example: {@code diamond.paint(g,caller)}
+ * + * @param g + * the graphics object + * @param caller + * the Program Window or panel + */ + @Override + public void paint(Graphics2D g, JPanel caller) + { + Color color2 = PenColors.getTransparentVersion(mainColor, percentTransparent); + g.setColor(color2); + int width = 400; + int height = 300; + g.rotate(50); + g.fillRect(x, y, width, height); + } + /** + * Sets the transparency of the diamond + *
Example: {@code diamond.setTransparency(80)}
+ * + * @param percentTransparent + * The percentage of transparency of the diamond + */ + public void setTransparency(int percentTransparent) + { + this.percentTransparent = percentTransparent; + } + public void removeFrom(ProgramWindow panel) + { + panel.remove(this); + } + public int getX() + { + return this.x; + } + public int getY() + { + return this.y; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/ImageBackground.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/ImageBackground.java new file mode 100644 index 00000000..112c541c --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/ImageBackground.java @@ -0,0 +1,35 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.net.URL; + +import javax.imageio.ImageIO; +import javax.swing.JPanel; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; + +public class ImageBackground implements Paintable +{ + private BufferedImage image; + public ImageBackground(String uri) + { + try + { + URL url = new URL(uri); + image = ImageIO.read(url); + } + catch (Throwable e) + { + throw ObjectUtils.throwAsError(e); + } + } + @Override + public void paint(Graphics2D g, JPanel caller) + { + Image img = image; + g.drawImage(img, 0, 0, caller.getWidth(), caller.getHeight(), 0, 0, img.getWidth(null), img.getHeight(null), + null); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/LineSegment.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/LineSegment.java new file mode 100644 index 00000000..bad9b283 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/LineSegment.java @@ -0,0 +1,36 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +import java.awt.Color; +import java.awt.Point; + +public class LineSegment +{ + private Color color; + private Point start; + private Point end; + private final int width; + public LineSegment(Color color, Point start, Point end, int width) + { + super(); + this.color = color; + this.start = start; + this.end = end; + this.width = width; + } + public Color getColor() + { + return color; + } + public Point getStart() + { + return start; + } + public Point getEnd() + { + return end; + } + public float getWidth() + { + return width; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Paintable.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Paintable.java new file mode 100644 index 00000000..510ce857 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Paintable.java @@ -0,0 +1,17 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +import java.awt.Graphics2D; + +import javax.swing.JPanel; + +public interface Paintable +{ + public static Paintable NOTHING = new Paintable() + { + @Override + public void paint(Graphics2D g, JPanel caller) + { + } + }; + void paint(Graphics2D g, JPanel caller); +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Text.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Text.java new file mode 100644 index 00000000..e2c065e6 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/LineAndShapeUtils/Text.java @@ -0,0 +1,92 @@ +package src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; + +import javax.swing.JPanel; + +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.ProgramWindow; +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.TurtleWindow; + +/** + * Some Text! + * Text allows you to write text on the window + */ +public class Text implements Paintable +{ + private final String string; + private int x; + private int y; + private Color color; +private TurtleWindow panel; + public Text(String string) + { + this.string = string; + } + /** + * Sets text position + *
Example: {@code text.setTopLeft(x,y)}
+ * + * @param x + * the X position + * @param y + * the Y position + * @return the same Text that you are working with + */ + public Text setTopLeft(int x, int y) + { + this.x = x; + this.y = y; + return this; + } + /** + * Adds text to the window + *
Example: {@code text.addTo(panel)}
+ * + * @param panel + * the ProgramWindow or panel + */ + public void addTo(src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.TurtleWindow panel) + { + this.panel = panel; + panel.getCanvas().add(this); + } + @Override + public void paint(Graphics2D g, JPanel caller) + { + Font font = g.getFont(); + Font font2 = new Font(font.getName(), font.getStyle() | Font.BOLD, font.getSize()); + if (this.color != null) + { + g.setColor(this.color); + } + g.setFont(font2); + g.drawString(string, x, y); + } + public Text setPenColor(Color color) + { + this.color = color; + return this; + } + public String getContent() + { + return this.string; + } + public Color getPenColor() + { + return this.color; + } + public int getX() + { + return this.x; + } + public int getY() + { + return this.y; + } + public void addTo(ProgramWindow programWindow) + { + programWindow.getCanvas().add(this); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MVCUtils/Parser.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MVCUtils/Parser.java new file mode 100644 index 00000000..f44c3952 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MVCUtils/Parser.java @@ -0,0 +1,97 @@ +package src.main.java.org.teachingextentions.logo.utils.MVCUtils; + +import java.lang.reflect.Field; +import java.util.List; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.FileUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.Function1; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.Query; + +/** + * A parser + * Parses a data object for display, using a template + */ +public class Parser +{ + /** + * Parses a template with a data object to create a string + * + *
Example:
{@code
+   * Words data = new Words();
+   * data.action = "Shake";
+   * data.weapon = "speare";
+   * String greeting = Parser.parse("Captain {action}{weapon}!!!", data);
+   * }
+ * + * Captain Shakespeare!!! + * + * @param text + * The template with the fields from the data object surrounded in {curlyBraces} + * @param data + * an object whose fields will be merged with the template during parsing + * @return the completed string + */ + public static String parse(String text, Object data) + { + return parse(text, "{", "}", data); + } + public static String parse(String text, String startCharacter, String endCharacter, Object data) + { + StringBuilder sb = new StringBuilder(); + String temp = text; + int start = temp.indexOf(startCharacter); + while (start > 0) + { + int end = temp.indexOf(endCharacter, start); + sb.append(temp.substring(0, start)); + String key = temp.substring(start + startCharacter.length(), end); + sb.append(getValue(key, data)); + temp = temp.substring(end + endCharacter.length()); + start = temp.indexOf(startCharacter); + } + sb.append(temp); + return sb.toString(); + } + private static String getValue(final String piece, Object data) + { + try + { + Field[] declaredFields = data.getClass().getDeclaredFields(); + List f = Query.where(declaredFields, new Function1() + { + @Override + public Boolean call(Field i) + { + return i.getName().equals(piece); + } + }); + f.get(0).setAccessible(true); + return "" + f.get(0).get(data); + } + catch (Exception e) + { + return piece; + } + } + /** + * Parses a file + *
Example: {@code parser.parseRtfFile(filename,data)}
+ * + * @param fileName A filename for the new file, built from the template view.rtf + * @param data A data object to put into the template fields. + * @return the completed template + */ + public static String parseRtfFile(String fileName, Object data) + { + try + { + String text = FileUtils.readFromClassPath(data.getClass(), fileName); + return parse(text, "\\{", "\\}", data); + } + catch (Exception e) + { + throw ObjectUtils.throwAsError(e); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MVCUtils/Viewer.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MVCUtils/Viewer.java new file mode 100644 index 00000000..c032614a --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MVCUtils/Viewer.java @@ -0,0 +1,39 @@ +package src.main.java.org.teachingextentions.logo.utils.MVCUtils; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.TestUtils; + +/** + * a view + * Displays a view via a template, populated with a data object + */ +public class Viewer +{ + /** + * Uses a RTF Viewer to display the results of a model (or text) + *
Example: {@code viewer.displayRtfFile(text)}
+ * + * @param text + * A model created from a String (text) + */ + public static void displayRtfFile(String text) + { + try + { + File file; + file = File.createTempFile("currentStory", ".rtf"); + FileWriter f = new FileWriter(file); + f.write(text); + f.close(); + TestUtils.displayFile(file.getPath()); + } + catch (IOException e) + { + throw ObjectUtils.throwAsError(e); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/CoolMaze.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/CoolMaze.java new file mode 100644 index 00000000..d2a42f3c --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/CoolMaze.java @@ -0,0 +1,187 @@ +package src.main.java.org.teachingextentions.logo.utils.MazeUtils; + +import java.awt.Color; + +public class CoolMaze +{ + public static void main(String[] args) + { + int mazeComplexityScale = 10; + CoolMaze maze = new CoolMaze(mazeComplexityScale); + StdDraw.show(0); + maze.drawWallsAndEndPoint(); + maze.solveThisMaze(); + } + public CoolMaze(int mazeComplexity) + { + this.mazeComplexity = mazeComplexity; + StdDraw.setXscale(0, mazeComplexity + 2); + StdDraw.setYscale(0, mazeComplexity + 2); + createMazeStructure(); + generateStartLocation(1, 1); + } + public void drawWallsAndEndPoint() + { + StdDraw.setPenColor(StdDrawColors.GREEN); + // createAndSizeStartPoint(); + createAndSizeEndPoint(); + drawAndColorMazeWalls(); + StdDraw.show(1000); + } + private void createMazeStructure() + { + visited = new boolean[mazeComplexity + 2][mazeComplexity + 2]; + for (int x = 0; x < mazeComplexity + 2; x++) + { + visited[x][0] = true; + visited[x][mazeComplexity + 1] = true; + } + for (int y = 0; y < mazeComplexity + 2; y++) + { + visited[0][y] = true; + visited[mazeComplexity + 1][y] = true; + } + north = new boolean[mazeComplexity + 2][mazeComplexity + 2]; + east = new boolean[mazeComplexity + 2][mazeComplexity + 2]; + south = new boolean[mazeComplexity + 2][mazeComplexity + 2]; + west = new boolean[mazeComplexity + 2][mazeComplexity + 2]; + for (int x = 0; x < mazeComplexity + 2; x++) + { + for (int y = 0; y < mazeComplexity + 2; y++) + { + north[x][y] = true; + east[x][y] = true; + south[x][y] = true; + west[x][y] = true; + } + } + } + private void generateStartLocation(int x, int y) + { + visited[x][y] = true; + while (!visited[x][y + 1] || !visited[x + 1][y] || !visited[x][y - 1] || !visited[x - 1][y]) + { + while (true) + { + double r = StdRandom.uniform(4); + if (r == 0 && !visited[x][y + 1]) + { + north[x][y] = false; + south[x][y + 1] = false; + generateStartLocation(x, y + 1); + break; + } + else if (r == 1 && !visited[x + 1][y]) + { + east[x][y] = false; + west[x + 1][y] = false; + generateStartLocation(x + 1, y); + break; + } + else if (r == 2 && !visited[x][y - 1]) + { + south[x][y] = false; + north[x][y - 1] = false; + generateStartLocation(x, y - 1); + break; + } + else if (r == 3 && !visited[x - 1][y]) + { + west[x][y] = false; + east[x - 1][y] = false; + generateStartLocation(x - 1, y); + break; + } + } + } + } + private void renderCorrectSolveDots(int x, int y) + { + Color colorOfCorrectSolvePath = StdDrawColors.BOOK_BLUE; + StdDraw.setPenColor(colorOfCorrectSolvePath); + drawAndSizeSolvePathPoints(x, y); + StdDraw.show(30); + } + private void renderIncorrectSolveDots(int x, int y) + { + Color colorOfIncorrectSolvePath = StdDrawColors.LIGHT_GRAY; + StdDraw.setPenColor(colorOfIncorrectSolvePath); + drawAndSizeSolvePathPoints(x, y); + StdDraw.show(30); + } + private void drawAndSizeSolvePathPoints(int x, int y) + { + StdDraw.filledCircle(x + 0.5, y + 0.5, 0.225); + } + private void createAndSizeEndPoint() + { + StdDraw.filledCircle(mazeComplexity / 2.0 + 0.5, mazeComplexity / 2.0 + 0.5, 0.35); + } + @SuppressWarnings("unused") + private void createAndSizeStartPoint() + { + StdDraw.filledCircle(1.5, 1.5, 0.35); + } + private void drawAndColorMazeWalls() + { + Color colorOfMazeWalls = StdDrawColors.DARK_GRAY; + StdDraw.setPenColor(colorOfMazeWalls); + drawMazeWalls(); + } + private void drawMazeWalls() + { + for (int x = 1; x <= mazeComplexity; x++) + { + for (int y = 1; y <= mazeComplexity; y++) + { + if (south[x][y]) + StdDraw.line(x, y, x + 1, y); + if (north[x][y]) + StdDraw.line(x, y + 1, x + 1, y + 1); + if (west[x][y]) + StdDraw.line(x, y, x, y + 1); + if (east[x][y]) + StdDraw.line(x + 1, y, x + 1, y + 1); + } + } + } + public void solveThisMaze() + { + int startingX = 1; + int startingY = 1; + for (int x = startingX; x <= mazeComplexity; x++) + for (int y = startingY; y <= mazeComplexity; y++) + visited[x][y] = false; + done = false; + solve(startingX, startingY); + } + private void solve(int x, int y) + { + if (x == 0 || y == 0 || x == mazeComplexity + 1 || y == mazeComplexity + 1) + return; + if (done || visited[x][y]) + return; + visited[x][y] = true; + renderCorrectSolveDots(x, y); + if (x == mazeComplexity / 2 && y == mazeComplexity / 2) + done = true; + if (!north[x][y]) + solve(x, y + 1); + if (!east[x][y]) + solve(x + 1, y); + if (!south[x][y]) + solve(x, y - 1); + if (!west[x][y]) + solve(x - 1, y); + if (done) + return; + renderIncorrectSolveDots(x, y); + } + private int mazeComplexity; + private boolean[][] north; + private boolean[][] east; + private boolean[][] south; + private boolean[][] west; + private boolean[][] visited; + private boolean done = false; +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/CreateMazeBackgroundFile.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/CreateMazeBackgroundFile.java new file mode 100644 index 00000000..114a255d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/CreateMazeBackgroundFile.java @@ -0,0 +1,91 @@ +package src.main.java.org.teachingextentions.logo.utils.MazeUtils; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.ImageIO; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.MySystem; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.TestUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ComponentApprovalWriter; +import src.main.java.org.teachingextentions.logo.utils.VirtualProctorUtils.ScreenCapture; + + +/*****in progress****/ +public class CreateMazeBackgroundFile extends WindowAdapter +{ + public static void main(String[] args) + { + CoolMaze maze1 = new CoolMaze(8); + maze1.drawWallsAndEndPoint(); + StdDraw.frame.addWindowListener(adapter); + closeTheWindow(); + } + private static void closeTheWindow() + { + StdDraw.frame.dispatchEvent(new WindowEvent(StdDraw.frame, WindowEvent.WINDOW_CLOSING)); + } + static WindowListener adapter = new WindowListener() + { + @Override + public void windowOpened(WindowEvent e) + { + } + @Override + public void windowClosing(WindowEvent e) + { + BufferedImage scaledMazeBackground = ScreenCapture.getScaledImageOf(e.getComponent(), 350, 350); + System.out.println("we got the window image, now what?"); + sendImageToDisk(scaledMazeBackground); + } + @Override + public void windowClosed(WindowEvent e) + { + } + @Override + public void windowIconified(WindowEvent e) + { + } + @Override + public void windowDeiconified(WindowEvent e) + { + } + @Override + public void windowActivated(WindowEvent e) + { + } + @Override + public void windowDeactivated(WindowEvent e) + { + } + }; + public static BufferedImage getImageOf(Component component, int width, int height) + { + BufferedImage image = ComponentApprovalWriter.drawComponent(component); + return image; + } + public static void sendImageToDisk(BufferedImage scaledMazeBackground) + { + try + { + Component c = StdDraw.frame.getComponent(0); + Graphics g = scaledMazeBackground.createGraphics(); + c.paint(g); + g.dispose(); + String filename = "./src/main/resources/mazeBackground/CoolMazeBackground.png"; + ImageIO.write(scaledMazeBackground, "png", new File(filename)); + //NOTE If you want to see the file that will be saved, uncomment the line below + TestUtils.displayFile(filename); + } + catch (Exception e) + { + MySystem.warning(e); + } + } + // NOTE: set this image as a background image for the TortoiseMaze recipe +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDraw.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDraw.java new file mode 100644 index 00000000..a72378b5 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDraw.java @@ -0,0 +1,1023 @@ +package src.main.java.org.teachingextentions.logo.utils.MazeUtils; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.FileDialog; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.MediaTracker; +import java.awt.RenderingHints; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Arc2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.DirectColorModel; +import java.awt.image.WritableRaster; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.LinkedList; +import java.util.NoSuchElementException; +import java.util.TreeSet; + +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; + +public final class StdDraw implements ActionListener, KeyListener +{ + private static final int DEFAULT_SIZE = 350; + private static int width = DEFAULT_SIZE; + private static int height = DEFAULT_SIZE; + private static final double DEFAULT_PEN_RADIUS = 0.0175; + private static double currentPenRadius; + private static boolean defer = false; + private static final double BORDER = 0.00; + private static final double DEFAULT_XMIN = 0.0; + private static final double DEFAULT_XMAX = 1.0; + private static final double DEFAULT_YMIN = 0.0; + private static final double DEFAULT_YMAX = 1.0; + private static double xmin, ymin, xmax, ymax; + private static final Font DEFAULT_FONT = new Font("SansSerif", Font.PLAIN, 16); + private static Font font; + private static BufferedImage offscreenImage, onscreenImage; + private static Graphics2D offscreen, onscreen; + private static StdDraw stdDraw = new StdDraw(); + public static JFrame frame; + private static Object keyLock = new Object(); + private static LinkedList keysTyped = new LinkedList(); + private static TreeSet keysDown = new TreeSet(); + private static long nextDrawInMS = -1; + private StdDraw() + { + } + static + { + init(); + } + public static void main(String[] args) + { + StdDraw.square(.2, .8, .1); + StdDraw.filledSquare(.8, .8, .2); + StdDraw.circle(.8, .2, .2); + StdDraw.setPenColor(StdDrawColors.BOOK_RED); + StdDraw.setPenRadius(.02); + StdDraw.arc(.8, .2, .1, 200, 45); + StdDraw.setPenRadius(); + StdDraw.setPenColor(StdDrawColors.BOOK_BLUE); + double[] x = {.1, .2, .3, .2}; + double[] y = {.2, .3, .2, .1}; + StdDraw.filledPolygon(x, y); + StdDraw.setPenColor(StdDrawColors.BLACK); + StdDraw.text(0.2, 0.5, "black text"); + StdDraw.setPenColor(StdDrawColors.WHITE); + StdDraw.text(0.8, 0.8, "white text"); + } + public static void setCanvasSize() + { + setCanvasSize(DEFAULT_SIZE, DEFAULT_SIZE); + } + public static void setCanvasSize(int canvasWidth, int canvasHeight) + { + if (width <= 0 || height <= 0) + throw new IllegalArgumentException("width and height must be positive"); + width = canvasWidth; + height = canvasHeight; + init(); + } + private static void init() + { + if (frame != null) + frame.setVisible(false); + frame = new JFrame(); + offscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + onscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + offscreen = offscreenImage.createGraphics(); + onscreen = onscreenImage.createGraphics(); + setXscale(); + setYscale(); + offscreen.setColor(StdDrawColors.DEFAULT_CLEAR_COLOR); + offscreen.fillRect(0, 0, width, height); + setPenColor(); + setPenRadius(); + setFont(); + clearScreenToWhite(); + RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + offscreen.addRenderingHints(hints); + ImageIcon icon = new ImageIcon(onscreenImage); + JLabel draw = new JLabel(icon); + frame.setContentPane(draw); + frame.addKeyListener(stdDraw); + frame.setResizable(false); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // close all windows + // frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // closes only current window + frame.setTitle("Amazing Maze!"); + frame.setJMenuBar(createMenuBar()); + frame.pack(); + frame.requestFocusInWindow(); + frame.setVisible(true); + // NOTE: This is not working, so mouse events won't work yet... + //draw.addMouseListener(stdDraw); + //draw.addMouseMotionListener(stdDraw); + MouseListener l = null; + draw.addMouseListener(l); + MouseMotionListener m = null; + draw.addMouseMotionListener(m); + } + private static JMenuBar createMenuBar() + { + JMenuBar menuBar = new JMenuBar(); + JMenu menu = new JMenu("File"); + menuBar.add(menu); + JMenuItem menuItem1 = new JMenuItem(" Save... "); + menuItem1.addActionListener(stdDraw); + menuItem1.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + menu.add(menuItem1); + return menuBar; + } + public static void setXscale() + { + setXscale(DEFAULT_XMIN, DEFAULT_XMAX); + } + public static void setYscale() + { + setYscale(DEFAULT_YMIN, DEFAULT_YMAX); + } + public static void setScale() + { + setXscale(); + setYscale(); + } + public static void setXscale(double min, double max) + { + double size = max - min; + if (size == 0.0) + throw new IllegalArgumentException("the min and max are the same"); + synchronized (StdDrawMouseEvents.mouseLock) + { + xmin = min - BORDER * size; + xmax = max + BORDER * size; + } + } + public static void setYscale(double min, double max) + { + double size = max - min; + if (size == 0.0) + throw new IllegalArgumentException("the min and max are the same"); + synchronized (StdDrawMouseEvents.mouseLock) + { + ymin = min - BORDER * size; + ymax = max + BORDER * size; + } + } + public static void setScale(double min, double max) + { + double size = max - min; + if (size == 0.0) + throw new IllegalArgumentException("the min and max are the same"); + synchronized (StdDrawMouseEvents.mouseLock) + { + xmin = min - BORDER * size; + xmax = max + BORDER * size; + ymin = min - BORDER * size; + ymax = max + BORDER * size; + } + } + private static double scaleX(double x) + { + return width * (x - xmin) / (xmax - xmin); + } + private static double scaleY(double y) + { + return height * (ymax - y) / (ymax - ymin); + } + private static double factorX(double w) + { + return w * width / Math.abs(xmax - xmin); + } + private static double factorY(double h) + { + return h * height / Math.abs(ymax - ymin); + } + static double userX(double x) + { + return xmin + x * (xmax - xmin) / width; + } + static double userY(double y) + { + return ymax - y * (ymax - ymin) / height; + } + public static void clearScreenToWhite() + { + clearScreenToColor(StdDrawColors.DEFAULT_CLEAR_COLOR); + } + public static void clearScreenToColor(Color color) + { + offscreen.setColor(color); + offscreen.fillRect(0, 0, width, height); + offscreen.setColor(StdDrawColors.currentPenColor); + draw(); + } + public static double getPenRadius() + { + return currentPenRadius; + } + public static void setPenRadius() + { + setPenRadius(DEFAULT_PEN_RADIUS); + } + public static void setPenRadius(double radius) + { + if (!(radius >= 0)) + throw new IllegalArgumentException("pen radius must be nonnegative"); + currentPenRadius = radius; + float scaledPenRadius = (float) (radius * DEFAULT_SIZE); + BasicStroke stroke = new BasicStroke(scaledPenRadius, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + offscreen.setStroke(stroke); + } + public static Color getPenColor() + { + return StdDrawColors.currentPenColor; + } + public static void setPenColor() + { + setPenColor(StdDrawColors.DEFAULT_PEN_COLOR); + } + public static void setPenColor(Color color) + { + if (color == null) + throw new NullPointerException(); + StdDrawColors.currentPenColor = color; + offscreen.setColor(StdDrawColors.currentPenColor); + } + public static void setPenColor(int red, int green, int blue) + { + if (red < 0 || red >= 256) + throw new IllegalArgumentException("amount of red must be between 0 and 255"); + if (green < 0 || green >= 256) + throw new IllegalArgumentException("amount of green must be between 0 and 255"); + if (blue < 0 || blue >= 256) + throw new IllegalArgumentException("amount of blue must be between 0 and 255"); + setPenColor(new Color(red, green, blue)); + } + public static Font getFont() + { + return font; + } + public static void setFont() + { + setFont(DEFAULT_FONT); + } + public static void setFont(Font font) + { + if (font == null) + throw new NullPointerException(); + StdDraw.font = font; + } + /** + * Draws a line segment between (x0, y0) and + * (x1, y1). + * + * @param x0 the x-coordinate of one endpoint + * @param y0 the y-coordinate of one endpoint + * @param x1 the x-coordinate of the other endpoint + * @param y1 the y-coordinate of the other endpoint + */ + public static void line(double x0, double y0, double x1, double y1) + { + offscreen.draw(new Line2D.Double(scaleX(x0), scaleY(y0), scaleX(x1), scaleY(y1))); + draw(); + } + /** + * Draws one pixel at (x, y). + * This method is private because pixels depend on the display. + * To achieve the same effect, set the pen radius to 0 and call {@code point()}. + * + * @param x the x-coordinate of the pixel + * @param y the y-coordinate of the pixel + */ + private static void pixel(double x, double y) + { + offscreen.fillRect((int) Math.round(scaleX(x)), (int) Math.round(scaleY(y)), 1, 1); + } + /** + * Draws a point centered at (x, y). + * The point is a filled circle whose radius is equal to the pen radius. + * To draw a single-pixel point, first set the pen radius to 0. + * + * @param x the x-coordinate of the point + * @param y the y-coordinate of the point + */ + public static void point(double x, double y) + { + double xs = scaleX(x); + double ys = scaleY(y); + double r = currentPenRadius; + float scaledPenRadius = (float) (r * DEFAULT_SIZE); + if (scaledPenRadius <= 1) + pixel(x, y); + else + offscreen.fill(new Ellipse2D.Double(xs - scaledPenRadius / 2, ys - scaledPenRadius / 2, scaledPenRadius, + scaledPenRadius)); + draw(); + } + /** + * Draws a circle of the specified radius, centered at (x, y). + * + * @param x the x-coordinate of the center of the circle + * @param y the y-coordinate of the center of the circle + * @param radius the radius of the circle + * @throws IllegalArgumentException if {@code radius} is negative + */ + public static void circle(double x, double y, double radius) + { + if (!(radius >= 0)) + throw new IllegalArgumentException("radius must be nonnegative"); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * radius); + double hs = factorY(2 * radius); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.draw(new Ellipse2D.Double(xs - ws / 2, ys - hs / 2, ws, hs)); + draw(); + } + /** + * Draws a filled circle of the specified radius, centered at (x, y). + * + * @param x the x-coordinate of the center of the circle + * @param y the y-coordinate of the center of the circle + * @param radius the radius of the circle + * @throws IllegalArgumentException if {@code radius} is negative + */ + public static void filledCircle(double x, double y, double radius) + { + if (!(radius >= 0)) + throw new IllegalArgumentException("radius must be nonnegative"); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * radius); + double hs = factorY(2 * radius); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.fill(new Ellipse2D.Double(xs - ws / 2, ys - hs / 2, ws, hs)); + draw(); + } + /** + * Draws an ellipse with the specified semimajor and semiminor axes, + * centered at (x, y). + * + * @param x the x-coordinate of the center of the ellipse + * @param y the y-coordinate of the center of the ellipse + * @param semiMajorAxis is the semimajor axis of the ellipse + * @param semiMinorAxis is the semiminor axis of the ellipse + * @throws IllegalArgumentException if either {@code semiMajorAxis} + * or {@code semiMinorAxis} is negative + */ + public static void ellipse(double x, double y, double semiMajorAxis, double semiMinorAxis) + { + if (!(semiMajorAxis >= 0)) + throw new IllegalArgumentException("ellipse semimajor axis must be nonnegative"); + if (!(semiMinorAxis >= 0)) + throw new IllegalArgumentException("ellipse semiminor axis must be nonnegative"); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * semiMajorAxis); + double hs = factorY(2 * semiMinorAxis); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.draw(new Ellipse2D.Double(xs - ws / 2, ys - hs / 2, ws, hs)); + draw(); + } + /** + * Draws an ellipse with the specified semimajor and semiminor axes, + * centered at (x, y). + * + * @param x the x-coordinate of the center of the ellipse + * @param y the y-coordinate of the center of the ellipse + * @param semiMajorAxis is the semimajor axis of the ellipse + * @param semiMinorAxis is the semiminor axis of the ellipse + * @throws IllegalArgumentException if either {@code semiMajorAxis} + * or {@code semiMinorAxis} is negative + */ + public static void filledEllipse(double x, double y, double semiMajorAxis, double semiMinorAxis) + { + if (!(semiMajorAxis >= 0)) + throw new IllegalArgumentException("ellipse semimajor axis must be nonnegative"); + if (!(semiMinorAxis >= 0)) + throw new IllegalArgumentException("ellipse semiminor axis must be nonnegative"); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * semiMajorAxis); + double hs = factorY(2 * semiMinorAxis); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.fill(new Ellipse2D.Double(xs - ws / 2, ys - hs / 2, ws, hs)); + draw(); + } + /** + * Draws a circular arc of the specified radius, + * centered at (x, y), from angle1 to angle2 (in degrees). + * + * @param x the x-coordinate of the center of the circle + * @param y the y-coordinate of the center of the circle + * @param radius the radius of the circle + * @param angle1 the starting angle. 0 would mean an arc beginning at 3 o'clock. + * @param angle2 the angle at the end of the arc. For example, if + * you want a 90 degree arc, then angle2 should be angle1 + 90. + * @throws IllegalArgumentException if {@code radius} is negative + */ + public static void arc(double x, double y, double radius, double angle1, double angle2) + { + if (radius < 0) + throw new IllegalArgumentException("arc radius must be nonnegative"); + while (angle2 < angle1) + angle2 += 360; + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * radius); + double hs = factorY(2 * radius); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.draw(new Arc2D.Double(xs - ws / 2, ys - hs / 2, ws, hs, angle1, angle2 - angle1, Arc2D.OPEN)); + draw(); + } + /** + * Draws a square of side length 2r, centered at (x, y). + * + * @param x the x-coordinate of the center of the square + * @param y the y-coordinate of the center of the square + * @param halfLength one half the length of any side of the square + * @throws IllegalArgumentException if {@code halfLength} is negative + */ + public static void square(double x, double y, double halfLength) + { + if (!(halfLength >= 0)) + throw new IllegalArgumentException("half length must be nonnegative"); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * halfLength); + double hs = factorY(2 * halfLength); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.draw(new Rectangle2D.Double(xs - ws / 2, ys - hs / 2, ws, hs)); + draw(); + } + /** + * Draws a filled square of the specified size, centered at (x, y). + * + * @param x the x-coordinate of the center of the square + * @param y the y-coordinate of the center of the square + * @param halfLength one half the length of any side of the square + * @throws IllegalArgumentException if {@code halfLength} is negative + */ + public static void filledSquare(double x, double y, double halfLength) + { + if (!(halfLength >= 0)) + throw new IllegalArgumentException("half length must be nonnegative"); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * halfLength); + double hs = factorY(2 * halfLength); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.fill(new Rectangle2D.Double(xs - ws / 2, ys - hs / 2, ws, hs)); + draw(); + } + /** + * Draws a rectangle of the specified size, centered at (x, y). + * + * @param x the x-coordinate of the center of the rectangle + * @param y the y-coordinate of the center of the rectangle + * @param halfWidth one half the width of the rectangle + * @param halfHeight one half the height of the rectangle + * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative + */ + public static void rectangle(double x, double y, double halfWidth, double halfHeight) + { + if (!(halfWidth >= 0)) + throw new IllegalArgumentException("half width must be nonnegative"); + if (!(halfHeight >= 0)) + throw new IllegalArgumentException("half height must be nonnegative"); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * halfWidth); + double hs = factorY(2 * halfHeight); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.draw(new Rectangle2D.Double(xs - ws / 2, ys - hs / 2, ws, hs)); + draw(); + } + /** + * Draws a filled rectangle of the specified size, centered at (x, y). + * + * @param x the x-coordinate of the center of the rectangle + * @param y the y-coordinate of the center of the rectangle + * @param halfWidth one half the width of the rectangle + * @param halfHeight one half the height of the rectangle + * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative + */ + public static void filledRectangle(double x, double y, double halfWidth, double halfHeight) + { + if (!(halfWidth >= 0)) + throw new IllegalArgumentException("half width must be nonnegative"); + if (!(halfHeight >= 0)) + throw new IllegalArgumentException("half height must be nonnegative"); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(2 * halfWidth); + double hs = factorY(2 * halfHeight); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + offscreen.fill(new Rectangle2D.Double(xs - ws / 2, ys - hs / 2, ws, hs)); + draw(); + } + /** + * Draws a polygon with the vertices + * (x0, y0), + * (x1, y1), ..., + * (xn−1, yn−1). + * + * @param x an array of all the x-coordinates of the polygon + * @param y an array of all the y-coordinates of the polygon + * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} + * are of the same length + */ + public static void polygon(double[] x, double[] y) + { + if (x == null) + throw new NullPointerException(); + if (y == null) + throw new NullPointerException(); + int n1 = x.length; + int n2 = y.length; + if (n1 != n2) + throw new IllegalArgumentException("arrays must be of the same length"); + int n = n1; + GeneralPath path = new GeneralPath(); + path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); + for (int i = 0; i < n; i++) + path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); + path.closePath(); + offscreen.draw(path); + draw(); + } + /** + * Draws a polygon with the vertices + * (x0, y0), + * (x1, y1), ..., + * (xn−1, yn−1). + * + * @param x an array of all the x-coordinates of the polygon + * @param y an array of all the y-coordinates of the polygon + * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} + * are of the same length + */ + public static void filledPolygon(double[] x, double[] y) + { + if (x == null) + throw new NullPointerException(); + if (y == null) + throw new NullPointerException(); + int n1 = x.length; + int n2 = y.length; + if (n1 != n2) + throw new IllegalArgumentException("arrays must be of the same length"); + int n = n1; + GeneralPath path = new GeneralPath(); + path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); + for (int i = 0; i < n; i++) + path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); + path.closePath(); + offscreen.fill(path); + draw(); + } + private static Image getImageFromFile(String filename) + { + if (filename == null) + throw new NullPointerException(); + ImageIcon icon = new ImageIcon(filename); + if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) + { + try + { + URL url = new URL(filename); + icon = new ImageIcon(url); + } + catch (Exception e) + { + } + } + if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) + { + // in case file is inside a .jar (classpath relative to StdDraw) + URL url = StdDraw.class.getResource(filename); + if (url != null) + icon = new ImageIcon(url); + } + if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) + { + // in case file is inside a .jar (classpath relative to root of jar) + URL url = StdDraw.class.getResource("/" + filename); + if (url == null) + throw new IllegalArgumentException("image " + filename + " not found"); + icon = new ImageIcon(url); + } + return icon.getImage(); + } + /** + * Draws the specified image centered at (x, y). + * The supported image formats are JPEG, PNG, and GIF. + * As an optimization, the picture is cached, so there is no performance + * penalty for redrawing the same image multiple times (e.g., in an animation). + * However, if you change the picture file after drawing it, subsequent + * calls will draw the original picture. + * + * @param x the center x-coordinate of the image + * @param y the center y-coordinate of the image + * @param filename the name of the image/picture, e.g., "ball.gif" + * @throws IllegalArgumentException if the image filename is invalid + */ + public static void picture(double x, double y, String filename) + { + Image image = getImageFromFile(filename); + double xs = scaleX(x); + double ys = scaleY(y); + int ws = image.getWidth(null); + int hs = image.getHeight(null); + if (ws < 0 || hs < 0) + throw new IllegalArgumentException("image " + filename + " is corrupt"); + offscreen.drawImage(image, (int) Math.round(xs - ws / 2.0), (int) Math.round(ys - hs / 2.0), null); + draw(); + } + /** + * Draws the specified image centered at (x, y), + * rotated given number of degrees. + * The supported image formats are JPEG, PNG, and GIF. + * + * @param x the center x-coordinate of the image + * @param y the center y-coordinate of the image + * @param filename the name of the image/picture, e.g., "ball.gif" + * @param degrees is the number of degrees to rotate counterclockwise + * @throws IllegalArgumentException if the image filename is invalid + */ + public static void picture(double x, double y, String filename, double degrees) + { + Image image = getImageFromFile(filename); + double xs = scaleX(x); + double ys = scaleY(y); + int ws = image.getWidth(null); + int hs = image.getHeight(null); + if (ws < 0 || hs < 0) + throw new IllegalArgumentException("image " + filename + " is corrupt"); + offscreen.rotate(Math.toRadians(-degrees), xs, ys); + offscreen.drawImage(image, (int) Math.round(xs - ws / 2.0), (int) Math.round(ys - hs / 2.0), null); + offscreen.rotate(Math.toRadians(+degrees), xs, ys); + draw(); + } + /** + * Draws the specified image centered at (x, y), + * rescaled to the specified bounding box. + * The supported image formats are JPEG, PNG, and GIF. + * + * @param x the center x-coordinate of the image + * @param y the center y-coordinate of the image + * @param filename the name of the image/picture, e.g., "ball.gif" + * @param scaledWidth the width of the scaled image in pixels + * @param scaledHeight the height of the scaled image in pixels + * @throws IllegalArgumentException if either {@code scaledWidth} + * or {@code scaledHeight} is negative + * @throws IllegalArgumentException if the image filename is invalid + */ + public static void picture(double x, double y, String filename, double scaledWidth, double scaledHeight) + { + Image image = getImageFromFile(filename); + if (scaledWidth < 0) + throw new IllegalArgumentException("width is negative: " + scaledWidth); + if (scaledHeight < 0) + throw new IllegalArgumentException("height is negative: " + scaledHeight); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(scaledWidth); + double hs = factorY(scaledHeight); + if (ws < 0 || hs < 0) + throw new IllegalArgumentException("image " + filename + " is corrupt"); + if (ws <= 1 && hs <= 1) + pixel(x, y); + else + { + offscreen.drawImage(image, (int) Math.round(xs - ws / 2.0), (int) Math.round(ys - hs / 2.0), + (int) Math.round(ws), (int) Math.round(hs), null); + } + draw(); + } + /** + * Draws the specified image centered at (x, y), rotated + * given number of degrees, and rescaled to the specified bounding box. + * The supported image formats are JPEG, PNG, and GIF. + * + * @param x the center x-coordinate of the image + * @param y the center y-coordinate of the image + * @param filename the name of the image/picture, e.g., "ball.gif" + * @param scaledWidth the width of the scaled image in pixels + * @param scaledHeight the height of the scaled image in pixels + * @param degrees is the number of degrees to rotate counterclockwise + * @throws IllegalArgumentException if either {@code scaledWidth} + * or {@code scaledHeight} is negative + * @throws IllegalArgumentException if the image filename is invalid + */ + public static void picture(double x, double y, String filename, double scaledWidth, double scaledHeight, + double degrees) + { + if (scaledWidth < 0) + throw new IllegalArgumentException("width is negative: " + scaledWidth); + if (scaledHeight < 0) + throw new IllegalArgumentException("height is negative: " + scaledHeight); + Image image = getImageFromFile(filename); + double xs = scaleX(x); + double ys = scaleY(y); + double ws = factorX(scaledWidth); + double hs = factorY(scaledHeight); + if (ws < 0 || hs < 0) + throw new IllegalArgumentException("image " + filename + " is corrupt"); + if (ws <= 1 && hs <= 1) + pixel(x, y); + offscreen.rotate(Math.toRadians(-degrees), xs, ys); + offscreen.drawImage(image, (int) Math.round(xs - ws / 2.0), (int) Math.round(ys - hs / 2.0), + (int) Math.round(ws), (int) Math.round(hs), null); + offscreen.rotate(Math.toRadians(+degrees), xs, ys); + draw(); + } + /** + * Write the given text string in the current font, centered at (x, y). + * + * @param x the center x-coordinate of the text + * @param y the center y-coordinate of the text + * @param text the text to write + */ + public static void text(double x, double y, String text) + { + if (text == null) + throw new NullPointerException(); + offscreen.setFont(font); + FontMetrics metrics = offscreen.getFontMetrics(); + double xs = scaleX(x); + double ys = scaleY(y); + int ws = metrics.stringWidth(text); + int hs = metrics.getDescent(); + offscreen.drawString(text, (float) (xs - ws / 2.0), (float) (ys + hs)); + draw(); + } + /** + * Write the given text string in the current font, centered at (x, y) and + * rotated by the specified number of degrees. + * @param x the center x-coordinate of the text + * @param y the center y-coordinate of the text + * @param text the text to write + * @param degrees is the number of degrees to rotate counterclockwise + */ + public static void text(double x, double y, String text, double degrees) + { + if (text == null) + throw new NullPointerException(); + double xs = scaleX(x); + double ys = scaleY(y); + offscreen.rotate(Math.toRadians(-degrees), xs, ys); + text(x, y, text); + offscreen.rotate(Math.toRadians(+degrees), xs, ys); + } + /** + * Write the given text string in the current font, left-aligned at (x, y). + * @param x the x-coordinate of the text + * @param y the y-coordinate of the text + * @param text the text + */ + public static void textLeft(double x, double y, String text) + { + if (text == null) + throw new NullPointerException(); + offscreen.setFont(font); + FontMetrics metrics = offscreen.getFontMetrics(); + double xs = scaleX(x); + double ys = scaleY(y); + int hs = metrics.getDescent(); + offscreen.drawString(text, (float) xs, (float) (ys + hs)); + draw(); + } + /** + * Write the given text string in the current font, right-aligned at (x, y). + * + * @param x the x-coordinate of the text + * @param y the y-coordinate of the text + * @param text the text to write + */ + public static void textRight(double x, double y, String text) + { + if (text == null) + throw new NullPointerException(); + offscreen.setFont(font); + FontMetrics metrics = offscreen.getFontMetrics(); + double xs = scaleX(x); + double ys = scaleY(y); + int ws = metrics.stringWidth(text); + int hs = metrics.getDescent(); + offscreen.drawString(text, (float) (xs - ws), (float) (ys + hs)); + draw(); + } + public static void show(int t) + { + long millis = System.currentTimeMillis(); + if (millis < nextDrawInMS) + { + try + { + Thread.sleep(nextDrawInMS - millis); + } + catch (InterruptedException e) + { + System.out.println("Error sleeping"); + } + millis = nextDrawInMS; + } + defer = false; + draw(); + defer = true; + nextDrawInMS = millis + t; + } + /** + * Display on-screen and turn off animation mode: + * subsequent calls to + * drawing methods such as {@code line()}, {@code circle()}, + * and {@code square()} will be displayed on screen when called. + * This is the default. + */ + public static void show() + { + defer = false; + nextDrawInMS = -1; + draw(); + } + private static void draw() + { + if (defer) + return; + onscreen.drawImage(offscreenImage, 0, 0, null); + frame.repaint(); + } + /** + * Saves the drawing to using the specified filename. + * The supported image formats are JPEG and PNG; + * the filename suffix must be .jpg or .png. + * + * @param filename the name of the file with one of the required suffixes + */ + public static void save(String filename) + { + if (filename == null) + throw new NullPointerException(); + File file = new File(filename); + String suffix = filename.substring(filename.lastIndexOf('.') + 1); + if (suffix.toLowerCase().equals("png")) + { + try + { + ImageIO.write(onscreenImage, suffix, file); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else if (suffix.toLowerCase().equals("jpg")) + { + WritableRaster raster = onscreenImage.getRaster(); + WritableRaster newRaster; + newRaster = raster.createWritableChild(0, 0, width, height, 0, 0, new int[]{0, 1, 2}); + DirectColorModel cm = (DirectColorModel) onscreenImage.getColorModel(); + DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(), cm.getRedMask(), cm.getGreenMask(), + cm.getBlueMask()); + BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null); + try + { + ImageIO.write(rgbBuffer, suffix, file); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else + { + System.out.println("Invalid image file type: " + suffix); + } + } + @Override + public void actionPerformed(ActionEvent e) + { + FileDialog chooser = new FileDialog(StdDraw.frame, "Use a .png or .jpg extension", FileDialog.SAVE); + chooser.setVisible(true); + String filename = chooser.getFile(); + if (filename != null) + { + StdDraw.save(chooser.getDirectory() + File.separator + chooser.getFile()); + } + } + public static boolean isNextKeyTyped() + { + synchronized (keyLock) + { + return !keysTyped.isEmpty(); + } + } + /** + * Returns the next key that was typed by the user (that your program has not already processed). + * This method should be preceded by a call to {@link #isNextKeyTyped()} to ensure + * that there is a next key to process. + * This method returns a Unicode character corresponding to the key + * typed (such as {@code 'a'} or {@code 'A'}). + * It cannot identify action keys (such as F1 and arrow keys) + * or modifier keys (such as control). + * + * @return the next key typed by the user (that your program has not already processed). + * @throws NoSuchElementException if there is no remaining key + */ + public static char nextKeyTyped() + { + synchronized (keyLock) + { + if (keysTyped + .isEmpty()) { throw new NoSuchElementException("your program has already processed all keystrokes"); } + return keysTyped.removeLast(); + } + } + /** + * Returns true if the given key is being pressed. + *

+ * This method takes the keycode (corresponding to a physical key) + * as an argument. It can handle action keys + * (such as F1 and arrow keys) and modifier keys (such as shift and control). + * See {@link KeyEvent} for a description of key codes. + * + * @param keycode the key to check if it is being pressed + * @return true if {@code keycode} is currently being pressed; + * false otherwise + */ + public static boolean isKeyPressed(int keycode) + { + synchronized (keyLock) + { + return keysDown.contains(keycode); + } + } + @Override + public void keyTyped(KeyEvent e) + { + synchronized (keyLock) + { + keysTyped.addFirst(e.getKeyChar()); + } + } + @Override + public void keyPressed(KeyEvent e) + { + synchronized (keyLock) + { + keysDown.add(e.getKeyCode()); + } + } + @Override + public void keyReleased(KeyEvent e) + { + synchronized (keyLock) + { + keysDown.remove(e.getKeyCode()); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawColors.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawColors.java new file mode 100644 index 00000000..f4d98f8c --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawColors.java @@ -0,0 +1,30 @@ +package src.main.java.org.teachingextentions.logo.utils.MazeUtils; + +import java.awt.Color; + +public class StdDrawColors +{ + public static final Color BLACK = Color.BLACK; + public static final Color BLUE = Color.BLUE; + public static final Color CYAN = Color.CYAN; + public static final Color DARK_GRAY = Color.DARK_GRAY; + public static final Color GRAY = Color.GRAY; + public static final Color GREEN = Color.GREEN; + public static final Color LIGHT_GRAY = Color.LIGHT_GRAY; + public static final Color MAGENTA = Color.MAGENTA; + public static final Color ORANGE = Color.ORANGE; + public static final Color PINK = Color.PINK; + public static final Color RED = Color.RED; + public static final Color WHITE = Color.WHITE; + public static final Color YELLOW = Color.YELLOW; + public static final Color BOOK_BLUE = new Color(9, 90, 166); + public static final Color BOOK_LIGHT_BLUE = new Color(103, 198, 243); + public static final Color BOOK_RED = new Color(150, 35, 31); + static final Color DEFAULT_PEN_COLOR = BLACK; + static final Color DEFAULT_CLEAR_COLOR = WHITE; + static Color currentPenColor; + public static void main(String[] args) + { + + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawComments.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawComments.java new file mode 100644 index 00000000..ab64098f --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawComments.java @@ -0,0 +1,349 @@ +/** + *

+ * Example code + *

+ *

+ *   public class TestStdDraw {
+ *       public static void main(String[] args) {
+ *           StdDraw.setPenRadius(0.05);
+ *           StdDraw.setPenColor(StdDraw.BLUE);
+ *           StdDraw.point(0.5, 0.5);
+ *           StdDraw.setPenColor(StdDraw.MAGENTA);
+ *           StdDraw.line(0.2, 0.2, 0.8, 0.2);
+ *       }
+ *   }
+ *  
+ *

+ * Points and lines. + *

    + *
  • {@link #point(double x, double y)} + *
  • {@link #line(double x1, double y1, double x2, double y2)} + *
+ *

+ * The x- and y-coordinates must be in the drawing area + * (between 0 and 1 and by default) or the points and lines will not be visible. + *

+ * Squares, circles, rectangles, and ellipses. + * You can draw squares, circles, rectangles, and ellipses using + * the following methods: + *

    + *
  • {@link #circle(double x, double y, double radius)} + *
  • {@link #ellipse(double x, double y, double semiMajorAxis, double semiMinorAxis)} + *
  • {@link #square(double x, double y, double radius)} + *
  • {@link #rectangle(double x, double y, double halfWidth, double halfHeight)} + *
+ *

+ * All of these methods take as arguments the location and size of the shape. + * The location is always specified by the x- and y-coordinates + * of its center. + * The size of a circle is specified by its radius and the size of an ellipse is + * specified by the lengths of its semi-major and semi-minor axes. + * The size of a square or rectangle is specified by its half-width or half-height. + * The convention for drawing squares and rectangles is parallel to those for + * drawing circles and ellipses, but may be unexpected to the uninitiated. + *

+ * The methods above trace outlines of the given shapes. The following methods + * draw filled versions: + *

    + *
  • {@link #filledCircle(double x, double y, double radius)} + *
  • {@link #filledEllipse(double x, double y, double semiMajorAxis, double semiMinorAxis)} + *
  • {@link #filledSquare(double x, double y, double radius)} + *
  • {@link #filledRectangle(double x, double y, double halfWidth, double halfHeight)} + *
+ *

+ * Circular arcs. + * You can draw circular arcs with the following method: + *

    + *
  • {@link #arc(double x, double y, double radius, double angle1, double angle2)} + *
+ *

+ * The arc is from the circle centered at (x, y) of the specified radius. + * The arc extends from angle1 to angle2. By convention, the angles are + * polar (counterclockwise angle from the x-axis) + * and represented in degrees. For example, {@code StdDraw.arc(0.0, 0.0, 1.0, 0, 90)} + * draws the arc of the unit circle from 3 o'clock (0 degrees) to 12 o'clock (90 degrees). + *

+ * Polygons. + * You can draw polygons with the following methods: + *

    + *
  • {@link #polygon(double[] x, double[] y)} + *
  • {@link #filledPolygon(double[] x, double[] y)} + *
+ *

+ * The points in the polygon are ({@code x[i]}, {@code y[i]}). + * For example, the following code fragment draws a filled diamond + * with vertices (0.1, 0.2), (0.2, 0.3), (0.3, 0.2), and (0.2, 0.1): + *

+ *   double[] x = { 0.1, 0.2, 0.3, 0.2 };
+ *   double[] y = { 0.2, 0.3, 0.2, 0.1 };
+ *   StdDraw.filledPolygon(x, y);
+ *  
+ *

+ * Pen size. + * The pen is circular, so that when you set the pen radius to r + * and draw a point, you get a circle of radius r. Also, lines are + * of thickness 2r and have rounded ends. The default pen radius + * is 0.005 and is not affected by coordinate scaling. This default pen + * radius is about 1/200 the width of the default canvas, so that if + * you draw 100 points equally spaced along a horizontal or vertical line, + * you will be able to see individual circles, but if you draw 200 such + * points, the result will look like a line. + *

    + *
  • {@link #setPenRadius(double radius)} + *
+ *

+ * For example, {@code StdDraw.setPenRadius(0.025)} makes + * the thickness of the lines and the size of the points to be five times + * the 0.005 default. + * To draw points with the minimum possible radius (one pixel on typical + * displays), set the pen radius to 0.0. + *

+ * Pen color. + * All geometric shapes (such as points, lines, and circles) are drawn using + * the current pen color. By default, it is black. + * You can change the pen color with the following methods: + *

    + *
  • {@link #setPenColor(int red, int green, int blue)} + *
  • {@link #setPenColor(Color color)} + *
+ *

+ * The first method allows you to specify colors using the RGB color system. + * This color picker + * is a convenient way to find a desired color. + * The second method allows you to specify colors using the + * {@link Color} data type that is discussed in Chapter 3. Until then, + * you can use this method with one of these predefined colors in standard drawing: + * {@link #BLACK}, {@link #BLUE}, {@link #CYAN}, {@link #DARK_GRAY}, {@link #GRAY}, + * {@link #GREEN}, {@link #LIGHT_GRAY}, {@link #MAGENTA}, {@link #ORANGE}, + * {@link #PINK}, {@link #RED}, {@link #WHITE}, and {@link #YELLOW}. + * For example, {@code StdDraw.setPenColor(StdDraw.MAGENTA)} sets the + * pen color to magenta. + *

+ * Canvas size. + * By default, all drawing takes places in a 512-by-512 canvas. + * The canvas does not include the window title or window border. + * You can change the size of the canvas with the following method: + *

    + *
  • {@link #setCanvasSize(int width, int height)} + *
+ *

+ * This sets the canvas size to be width-by-height pixels. + * It also erases the current drawing and resets the coordinate system, + * pen radius, pen color, and font back to their default values. + * Ordinarly, this method is called once, at the very beginning of a program. + * For example, {@code StdDraw.setCanvasSize(800, 800)} + * sets the canvas size to be 800-by-800 pixels. + *

+ * Canvas scale and coordinate system. + * By default, all drawing takes places in the unit square, with (0, 0) at + * lower left and (1, 1) at upper right. You can change the default + * coordinate system with the following methods: + *

    + *
  • {@link #setXscale(double xmin, double xmax)} + *
  • {@link #setYscale(double ymin, double ymax)} + *
  • {@link #setScale(double min, double max)} + *
+ *

+ * The arguments are the coordinates of the minimum and maximum + * x- or y-coordinates that will appear in the canvas. + * For example, if you wish to use the default coordinate system but + * leave a small margin, you can call {@code StdDraw.setScale(-.05, 1.05)}. + *

+ * These methods change the coordinate system for subsequent drawing + * commands; they do not affect previous drawings. + * These methods do not change the canvas size; so, if the x- + * and y-scales are different, squares will become rectangles + * and circles will become ellipsoidal. + *

+ * Text. + * You can use the following methods to annotate your drawings with text: + *

    + *
  • {@link #text(double x, double y, String text)} + *
  • {@link #text(double x, double y, String text, double degrees)} + *
  • {@link #textLeft(double x, double y, String text)} + *
  • {@link #textRight(double x, double y, String text)} + *
+ *

+ * The first two methods write the specified text in the current font, + * centered at (x, y). + * The second method allows you to rotate the text. + * The last two methods either left- or right-align the text at (x, y). + *

+ * The default font is a Sans Serif font with point size 16. + * You can use the following method to change the font: + *

    + *
  • {@link #setFont(Font font)} + *
+ *

+ * You use the {@link Font} data type to specify the font. This allows you to + * choose the face, size, and style of the font. For example, the following + * code fragment sets the font to Arial Bold, 60 point. + *

+ *   Font font = new Font("Arial", Font.BOLD, 60);
+ *   StdDraw.setFont(font);
+ *   StdDraw.text(0.5, 0.5, "Hello, World");
+ *  
+ *

+ * Images. + * You can use the following methods to add images to your drawings: + *

    + *
  • {@link #picture(double x, double y, String filename)} + *
  • {@link #picture(double x, double y, String filename, double degrees)} + *
  • {@link #picture(double x, double y, String filename, double width)} + *
  • {@link #picture(double x, double y, String filename, double width, double degrees)} + *
+ *

+ * These methods draw the specified image, centered at (x, y). + * The supported image formats are JPEG, PNG, and GIF. + * The image will display at its native size, independent of the coordinate system. + * Optionally, you can rotate the image a specified number of degrees counterclockwise + * or rescale it to fit inside a width-by-height pixel bounding box. + *

+ * Saving to a file. + * You save your image to a file using the File -> Save menu option. + * You can also save a file programatically using the following method: + *

    + *
  • {@link #save(String filename)} + *
+ *

+ * The supported image formats are JPEG and PNG. The filename must have either the + * extension .jpg or .png. + * We recommend using PNG for drawing that consist solely of geometric shapes and JPEG + * for drawings that contains pictures. + *

+ * Clearing the canvas. + * To clearWindow the entire drawing canvas, you can use the following methods: + *

    + *
  • {@link #clearScreenToWhite()} + *
  • {@link #clearScreenToColor(Color color)} + *
+ *

+ * The first method clears the canvas to white; the second method + * allows you to specify a color of your choice. For example, + * {@code StdDraw.clearWindow(StdDraw.LIGHT_GRAY)} clears the canvas to a shade + * of gray. Most often, these two methods are used in conjunction with animation mode. + *

+ * Animations. + * Animation mode is one of the trickier features of standard drawing. + * The following two methods control the way in which objects are drawn: + *

    + *
  • {@link #show()} + *
  • {@link #show(int t)} + *
+ *

+ * By default, animation mode is off, which means that as soon as you + * call a drawing + * method—such as {@code point()} or {@code line()}—the + * results appear on the screen. {@code StdDraw.show()} turns off + * animation mode. + *

+ * You can call {@link #show(int t)} to turn on animation mode. This + * defers all drawing to the screen until you are aready to display them. + * Once you are ready to display them, + * you call {@link #show(int t)} again, which transfer the offscreen + * drawing to the screen and waits for the specified number of milliseconds. + * In conjuction with {@link #clearScreenToWhite()}, you can create the illusion + * of movement by iterating the following three steps: + *

    + *
  • Clear the background canvas. + *
  • Draw geometric objects. + *
  • Show the drawing and wait for a short while. + *
+ *

+ * Waiting for a short while is essential; otherwise, the drawing will appear + * and disappear so quickly that your animation will flicker. + *

+ * Here is a simple example of an animation: + *

+ * Keyboard and mouse inputs. + * Standard drawing has very basic support for keyboard and mouse input. + * It is much less powerful than most user interface libraries provide, but also much simpler. + * You can use the following methods to intercept mouse events: + *

    + *
  • {@link #isMousePressed()} + *
  • {@link #mouseX()} + *
  • {@link #mouseY()} + *
+ *

+ * The first method tells you whether a mouse button is currently being pressed. + * The last two methods tells you the x- and y-coordinates of the mouse's + * current position, using the same coordinate system as the canvas (the unit square, by default). + * You should use these methods in an animation loop that waits a short while before trying + * to poll the mouse for its current state. + * You can use the following methods to intercept keyboard events: + *

    + *
  • {@link #isNextKeyTyped()} + *
  • {@link #nextKeyTyped()} + *
  • {@link #isKeyPressed(int keycode)} + *
+ *

+ * If the user types lots of keys, they will be saved in a list until you process them. + * The first method tells you whether the user has typed a key (that your program has + * not yet processed). + * The second method returns the next key that the user typed (that your program has + * not yet processed) and removes it from the list of saved keystrokes. + * The third method tells you whether a key is currently being pressed. + *

+ * Accessing control parameters. + * You can use the following methods to access the current pen color, pen radius, + * and font: + *

    + *
  • {@link #getPenColor()} + *
  • {@link #getPenRadius()} + *
  • {@link #getFont()} + *
+ *

+ * These methods are useful when you want to temporarily change a + * control parameter and reset it back to its original value. + *

+ * Corner cases. + * To avoid clutter, the API doesn't explicitly refer to arguments that are + * null, infinity, or NaN. + *

    + *
  • Any method that is passed a {@code null} argument will throw a + * {@link NullPointerException}. + *
  • Except as noted in the APIs, drawing an object outside (or partly outside) + * the canvas is permitted—however, only the part of the object that + * appears inside the canvas will be visible. + *
  • Except as noted in the APIs, all methods accept {@link Double#NaN}, + * {@link Double#POSITIVE_INFINITY}, and {@link Double#NEGATIVE_INFINITY} + * as arugments. An object drawn with an x- or y-coordinate + * that is NaN will behave as if it is outside the canvas, and will not be visible. + *
+ *

+ * Performance tricks. + * Standard drawing is capable of drawing large amounts of data. + * Here are a few tricks and tips: + *

    + *
  • Use animation mode for static drawing with a large + * number of objects. + * That is, call {@code StdDraw.show(0)} before + * and after the sequence of drawing commands. + * The bottleneck operation is not drawing the geometric + * shapes but rather drawing them to the screen. By using animation + * mode, you draw all of the shapes to an offscreen buffer, then copy + * them all at once to the screen. + *
  • When using animation mode, call {@code show()} + * only once per frame, not after drawing each object. + *
  • If you call {@code picture()} multiple times with the same filename, + * Java will cache the image, so you do not incur the cost of reading + * from a file each time. + *
  • Do not call {@code setFont()} in an animation loop (unless you really + * need to change the font in each iteration). It can cause flicker. + *
+ *

+ * Known bugs and issues. + *

    + *
  • The {@code picture()} methods may not draw the portion of the image that is + * inside the canvas if the center point (x, y) is outside the + * canvas. + * This bug appears only on some systems. + *
  • Some methods may not draw the portion of the geometric object that is inside the + * canvas if the x- or y-coordinates are infinite. + * This bug appears only on some systems. + *
+ *

+ * Authors + * @author Robert Sedgewick + * @author Kevin Wayne + */ \ No newline at end of file diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawMouseEvents.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawMouseEvents.java new file mode 100644 index 00000000..d2c1da33 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdDrawMouseEvents.java @@ -0,0 +1,82 @@ +package src.main.java.org.teachingextentions.logo.utils.MazeUtils; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +public class StdDrawMouseEvents implements MouseListener, MouseMotionListener +{ + public static Object mouseLock = new Object(); + private static boolean mousePressed = false; + private static double mouseX = 0; + private static double mouseY = 0; + public static boolean isMousePressed() + { + synchronized (mouseLock) + { + return mousePressed; + } + } + public static double mouseX() + { + synchronized (mouseLock) + { + return mouseX; + } + } + public static double mouseY() + { + synchronized (mouseLock) + { + return mouseY; + } + } + @Override + public void mouseClicked(MouseEvent e) + { + } + @Override + public void mouseEntered(MouseEvent e) + { + } + @Override + public void mouseExited(MouseEvent e) + { + } + @Override + public void mousePressed(MouseEvent e) + { + synchronized (mouseLock) + { + mouseX = StdDraw.userX(e.getX()); + mouseY = StdDraw.userY(e.getY()); + mousePressed = true; + } + } + @Override + public void mouseReleased(MouseEvent e) + { + synchronized (mouseLock) + { + mousePressed = false; + } + } + @Override + public void mouseDragged(MouseEvent e) + { + synchronized (mouseLock) + { + mouseX = StdDraw.userX(e.getX()); + mouseY = StdDraw.userY(e.getY()); + } + } + @Override + public void mouseMoved(MouseEvent e) + { + synchronized (mouseLock) + { + mouseX = StdDraw.userX(e.getX()); + mouseY = StdDraw.userY(e.getY()); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdOut.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdOut.java new file mode 100644 index 00000000..6a13ab4f --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdOut.java @@ -0,0 +1,316 @@ +package src.main.java.org.teachingextentions.logo.utils.MazeUtils; + +/****************************************************************************** + * Compilation: javac StdOut.java + * Execution: java StdOut + * Dependencies: none + * + * Writes data of various types to standard output. + * + ******************************************************************************/ +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.Locale; + +/** + * This class provides methods for printing strings and numbers to standard output. + *

+ * Getting started. + * To use this class, you must have StdOut.class in your + * Java classpath. If you used our autoinstaller, you should be all set. + * Otherwise, download + * StdOut.java + * and put a copy in your working directory. + *

+ * Here is an example program that uses StdOut: + *

+ *   public class TestStdOut {
+ *       public static void main(String[] args) {
+ *           int a = 17;
+ *           int b = 23;
+ *           int sum = a + b;
+ *           StdOut.println("Hello, World");
+ *           StdOut.printf("%d + %d = %d\n", a, b, sum);
+ *       }
+ *   }
+ *  
+ *

+ * Differences with System.out. + * The behavior of StdOut is similar to that of {@link System#out}, + * but there are a few subtle differences: + *

    + *
  • StdOut coerces the character-set encoding to UTF-8, + * which is a standard character encoding for Unicode. + *
  • StdOut coerces the locale to {@link Locale#US}, + * for consistency with {@link StdIn}, {@link Double#parseDouble(String)}, + * and floating-point literals. + *
  • StdOut flushes standard output after each call to + * print() so that text will appear immediately in the terminal. + *
+ *

+ * Reference. + * For additional documentation, + * see Section 1.5 of + * Introduction to Programming in Java: An Interdisciplinary Approach + * by Robert Sedgewick and Kevin Wayne. + * + * @author Robert Sedgewick + * @author Kevin Wayne + */ +public final class StdOut +{ + // force Unicode UTF-8 encoding; otherwise it's system dependent + private static final String CHARSET_NAME = "UTF-8"; + // assume language = English, country = US for consistency with StdIn + private static final Locale LOCALE = Locale.US; + // send output here + private static PrintWriter out; + // this is called before invoking any methods + static + { + try + { + out = new PrintWriter(new OutputStreamWriter(System.out, CHARSET_NAME), true); + } + catch (UnsupportedEncodingException e) + { + System.out.println(e); + } + } + // don't instantiate + private StdOut() + { + } + /** + * Closes standard output. + */ + public static void close() + { + out.close(); + } + /** + * Terminates the current line by printing the line-separator string. + */ + public static void println() + { + out.println(); + } + /** + * Prints an object to this output stream and then terminates the line. + * + * @param x the object to print + */ + public static void println(Object x) + { + out.println(x); + } + /** + * Prints a boolean to standard output and then terminates the line. + * + * @param x the boolean to print + */ + public static void println(boolean x) + { + out.println(x); + } + /** + * Prints a character to standard output and then terminates the line. + * + * @param x the character to print + */ + public static void println(char x) + { + out.println(x); + } + /** + * Prints a double to standard output and then terminates the line. + * + * @param x the double to print + */ + public static void println(double x) + { + out.println(x); + } + /** + * Prints an integer to standard output and then terminates the line. + * + * @param x the integer to print + */ + public static void println(float x) + { + out.println(x); + } + /** + * Prints an integer to standard output and then terminates the line. + * + * @param x the integer to print + */ + public static void println(int x) + { + out.println(x); + } + /** + * Prints a long to standard output and then terminates the line. + * + * @param x the long to print + */ + public static void println(long x) + { + out.println(x); + } + /** + * Prints a short integer to standard output and then terminates the line. + * + * @param x the short to print + */ + public static void println(short x) + { + out.println(x); + } + /** + * Prints a byte to standard output and then terminates the line. + *

+ * To write binary data, see {@link BinaryStdOut}. + * + * @param x the byte to print + */ + public static void println(byte x) + { + out.println(x); + } + /** + * Flushes standard output. + */ + public static void print() + { + out.flush(); + } + /** + * Prints an object to standard output and flushes standard output. + * + * @param x the object to print + */ + public static void print(Object x) + { + out.print(x); + out.flush(); + } + /** + * Prints a boolean to standard output and flushes standard output. + * + * @param x the boolean to print + */ + public static void print(boolean x) + { + out.print(x); + out.flush(); + } + /** + * Prints a character to standard output and flushes standard output. + * + * @param x the character to print + */ + public static void print(char x) + { + out.print(x); + out.flush(); + } + /** + * Prints a double to standard output and flushes standard output. + * + * @param x the double to print + */ + public static void print(double x) + { + out.print(x); + out.flush(); + } + /** + * Prints a float to standard output and flushes standard output. + * + * @param x the float to print + */ + public static void print(float x) + { + out.print(x); + out.flush(); + } + /** + * Prints an integer to standard output and flushes standard output. + * + * @param x the integer to print + */ + public static void print(int x) + { + out.print(x); + out.flush(); + } + /** + * Prints a long integer to standard output and flushes standard output. + * + * @param x the long integer to print + */ + public static void print(long x) + { + out.print(x); + out.flush(); + } + /** + * Prints a short integer to standard output and flushes standard output. + * + * @param x the short integer to print + */ + public static void print(short x) + { + out.print(x); + out.flush(); + } + /** + * Prints a byte to standard output and flushes standard output. + * + * @param x the byte to print + */ + public static void print(byte x) + { + out.print(x); + out.flush(); + } + /** + * Prints a formatted string to standard output, using the specified format + * string and arguments, and then flushes standard output. + * + * + * @param format the format string + * @param args the arguments accompanying the format string + */ + public static void printf(String format, Object... args) + { + out.printf(LOCALE, format, args); + out.flush(); + } + /** + * Prints a formatted string to standard output, using the locale and + * the specified format string and arguments; then flushes standard output. + * + * @param locale the locale + * @param format the format string + * @param args the arguments accompanying the format string + */ + public static void printf(Locale locale, String format, Object... args) + { + out.printf(locale, format, args); + out.flush(); + } + /** + * Unit tests some of the methods in StdOut. + */ + public static void main(String[] args) + { + // write to stdout + StdOut.println("Test"); + StdOut.println(17); + StdOut.println(true); + StdOut.printf("%.6f\n", 1.0 / 7.0); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdRandom.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdRandom.java new file mode 100644 index 00000000..ca326f61 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/MazeUtils/StdRandom.java @@ -0,0 +1,507 @@ +package src.main.java.org.teachingextentions.logo.utils.MazeUtils; + +/****************************************************************************** + * Compilation: javac StdRandom.java + * Execution: java StdRandom + * Dependencies: StdOut.java + * + * A library of static methods to generate pseudo-random numbers from + * different distributions (bernoulli, uniform, gaussian, discrete, + * and exponential). Also includes a method for shuffling an array. + * + * + * % java StdRandom 5 + * seed = 1316600602069 + * 59 16.81826 true 8.83954 0 + * 32 91.32098 true 9.11026 0 + * 35 10.11874 true 8.95396 3 + * 92 32.88401 true 8.87089 0 + * 72 92.55791 true 9.46241 0 + * + * % java StdRandom 5 + * seed = 1316600616575 + * 96 60.17070 true 8.72821 0 + * 79 32.01607 true 8.58159 0 + * 81 59.49065 true 9.10423 1 + * 96 51.65818 true 9.02102 0 + * 99 17.55771 true 8.99762 0 + * + * % java StdRandom 5 1316600616575 + * seed = 1316600616575 + * 96 60.17070 true 8.72821 0 + * 79 32.01607 true 8.58159 0 + * 81 59.49065 true 9.10423 1 + * 96 51.65818 true 9.02102 0 + * 99 17.55771 true 8.99762 0 + * + * + * Remark + * ------ + * - Relies on randomness of nextDouble() method in java.util.Random + * to generate pseudorandom numbers in [0, 1). + * + * - This library allows you to set and get the pseudorandom number seed. + * + * - See http://www.honeylocust.com/RngPack/ for an industrial + * strength random number generator in Java. + * + ******************************************************************************/ +import java.util.Random; + +/** + * The {@code StdRandom} class provides static methods for generating + * random number from various discrete and continuous distributions, + * including Bernoulli, uniform, Gaussian, exponential, pareto, + * Poisson, and Cauchy. It also provides method for shuffling an + * array or subarray. + *

+ * For additional documentation, + * see Section 2.2 of + * Introduction to Programming in Java: An Interdisciplinary Approach + * by Robert Sedgewick and Kevin Wayne. + * + * @author Robert Sedgewick + * @author Kevin Wayne + */ +public final class StdRandom +{ + private static Random random; // pseudo-random number generator + private static long seed; // pseudo-random number generator seed + // static initializer + static + { + // this is how the seed was set in Java 1.4 + seed = System.currentTimeMillis(); + random = new Random(seed); + } + // don't instantiate + private StdRandom() + { + } + /** + * Sets the seed of the pseudorandom number generator. + * This method enables you to produce the same sequence of "random" + * number for each execution of the program. + * Ordinarily, you should call this method at most once per program. + * + * @param s the seed + */ + public static void setSeed(long s) + { + seed = s; + random = new Random(seed); + } + /** + * Returns the seed of the pseudorandom number generator. + * + * @return the seed + */ + public static long getSeed() + { + return seed; + } + /** + * Returns a random real number uniformly in [0, 1). + * + * @return a random real number uniformly in [0, 1) + */ + public static double uniform() + { + return random.nextDouble(); + } + /** + * Returns a random integer uniformly in [0, n). + * + * @param n number of possible integers + * @return a random integer uniformly between 0 (inclusive) and N (exclusive) + * @throws IllegalArgumentException if n <= 0 + */ + public static int uniform(int n) + { + if (n <= 0) + throw new IllegalArgumentException("Parameter N must be positive"); + return random.nextInt(n); + } + /////////////////////////////////////////////////////////////////////////// + // STATIC METHODS BELOW RELY ON JAVA.UTIL.RANDOM ONLY INDIRECTLY VIA + // THE STATIC METHODS ABOVE. + /////////////////////////////////////////////////////////////////////////// + /** + * Returns a random real number uniformly in [0, 1). + * + * @return a random real number uniformly in [0, 1) + * @deprecated Replaced by {@link #uniform()}. + */ + @Deprecated + public static double random() + { + return uniform(); + } + /** + * Returns a random integer uniformly in [a, b). + * + * @param a the left endpoint + * @param b the right endpoint + * @return a random integer uniformly in [a, b) + * @throws IllegalArgumentException if b <= a + * @throws IllegalArgumentException if b - a >= Integer.MAX_VALUE + */ + public static int uniform(int a, int b) + { + if (b <= a) + throw new IllegalArgumentException("Invalid range"); + if ((long) b - a >= Integer.MAX_VALUE) + throw new IllegalArgumentException("Invalid range"); + return a + uniform(b - a); + } + /** + * Returns a random real number uniformly in [a, b). + * + * @param a the left endpoint + * @param b the right endpoint + * @return a random real number uniformly in [a, b) + * @throws IllegalArgumentException unless a < b + */ + public static double uniform(double a, double b) + { + if (!(a < b)) + throw new IllegalArgumentException("Invalid range"); + return a + uniform() * (b - a); + } + /** + * Returns a random boolean from a Bernoulli distribution with success + * probability p. + * + * @param p the probability of returning true + * @return true with probability p and + * false with probability p + * @throws IllegalArgumentException unless p >= 0.0 and p <= 1.0 + */ + public static boolean bernoulli(double p) + { + if (!(p >= 0.0 && p <= 1.0)) + throw new IllegalArgumentException("Probability must be between 0.0 and 1.0"); + return uniform() < p; + } + /** + * Returns a random boolean from a Bernoulli distribution with success + * probability 1/2. + * + * @return true with probability 1/2 and + * false with probability 1/2 + */ + public static boolean bernoulli() + { + return bernoulli(0.5); + } + /** + * Returns a random real number from a standard Gaussian distribution. + * + * @return a random real number from a standard Gaussian distribution + * (mean 0 and standard deviation 1). + */ + public static double gaussian() + { + // use the polar form of the Box-Muller transform + double r, x, y; + do + { + x = uniform(-1.0, 1.0); + y = uniform(-1.0, 1.0); + r = x * x + y * y; + } + while (r >= 1 || r == 0); + return x * Math.sqrt(-2 * Math.log(r) / r); + // Remark: y * Math.sqrt(-2 * Math.log(r) / r) + // is an independent random gaussian + } + /** + * Returns a random real number from a Gaussian distribution with mean μ + * and standard deviation σ. + * + * @param mu the mean + * @param sigma the standard deviation + * @return a real number distributed according to the Gaussian distribution + * with mean mu and standard deviation sigma + */ + public static double gaussian(double mu, double sigma) + { + return mu + sigma * gaussian(); + } + /** + * Returns a random integer from a geometric distribution with success + * probability p. + * + * @param p the parameter of the geometric distribution + * @return a random integer from a geometric distribution with success + * probability p + * @throws IllegalArgumentException unless p >= 0.0 and p <= 1.0 + */ + public static int geometric(double p) + { + if (!(p >= 0.0 && p <= 1.0)) + throw new IllegalArgumentException("Probability must be between 0.0 and 1.0"); + // using algorithm given by Knuth + return (int) Math.ceil(Math.log(uniform()) / Math.log(1.0 - p)); + } + /** + * Returns a random integer from a Poisson distribution with mean λ. + * + * @param lambda the mean of the Poisson distribution + * @return a random integer from a Poisson distribution with mean lambda + * @throws IllegalArgumentException unless lambda > 0.0 and not infinite + */ + public static int poisson(double lambda) + { + if (!(lambda > 0.0)) + throw new IllegalArgumentException("Parameter lambda must be positive"); + if (Double.isInfinite(lambda)) + throw new IllegalArgumentException("Parameter lambda must not be infinite"); + // using algorithm given by Knuth + // see http://en.wikipedia.org/wiki/Poisson_distribution + int k = 0; + double p = 1.0; + double L = Math.exp(-lambda); + do + { + k++; + p *= uniform(); + } + while (p >= L); + return k - 1; + } + /** + * Returns a random real number from the standard Pareto distribution. + * + * @return a random real number from the standard Pareto distribution + */ + public static double pareto() + { + return pareto(1.0); + } + /** + * Returns a random real number from a Pareto distribution with + * shape parameter α. + * + * @param alpha shape parameter + * @return a random real number from a Pareto distribution with shape + * parameter alpha + * @throws IllegalArgumentException unless alpha > 0.0 + */ + public static double pareto(double alpha) + { + if (!(alpha > 0.0)) + throw new IllegalArgumentException("Shape parameter alpha must be positive"); + return Math.pow(1 - uniform(), -1.0 / alpha) - 1.0; + } + /** + * Returns a random real number from the Cauchy distribution. + * + * @return a random real number from the Cauchy distribution. + */ + public static double cauchy() + { + return Math.tan(Math.PI * (uniform() - 0.5)); + } + /** + * Returns a random integer from the specified discrete distribution. + * + * @param a the probability of occurrence of each integer + * @return a random integer from a discrete distribution: + * i with probability a[i] + * @throws NullPointerException if a is null + * @throws IllegalArgumentException if sum of array entries is not (very nearly) equal to 1.0 + * @throws IllegalArgumentException unless a[i] >= 0.0 for each index i + */ + public static int discrete(double[] a) + { + if (a == null) + throw new NullPointerException("argument array is null"); + double EPSILON = 1E-14; + double sum = 0.0; + for (int i = 0; i < a.length; i++) + { + if (!(a[i] >= 0.0)) + throw new IllegalArgumentException("array entry " + i + " must be nonnegative: " + a[i]); + sum = sum + a[i]; + } + if (sum > 1.0 + EPSILON || sum < 1.0 - EPSILON) + throw new IllegalArgumentException("sum of array entries does not approximately equal 1.0: " + sum); + // the for loop may not return a value when both r is (nearly) 1.0 and when the + // cumulative sum is less than 1.0 (as a result of floating-point roundoff error) + while (true) + { + double r = uniform(); + sum = 0.0; + for (int i = 0; i < a.length; i++) + { + sum = sum + a[i]; + if (sum > r) + return i; + } + } + } + /** + * Returns a random real number from an exponential distribution + * with rate λ. + * + * @param lambda the rate of the exponential distribution + * @return a random real number from an exponential distribution with + * rate lambda + * @throws IllegalArgumentException unless lambda > 0.0 + */ + public static double exp(double lambda) + { + if (!(lambda > 0.0)) + throw new IllegalArgumentException("Rate lambda must be positive"); + return -Math.log(1 - uniform()) / lambda; + } + /** + * Rearranges the elements of the specified array in uniformly random order. + * + * @param a the array to shuffle + * @throws NullPointerException if a is null + */ + public static void shuffle(Object[] a) + { + if (a == null) + throw new NullPointerException("argument array is null"); + int N = a.length; + for (int i = 0; i < N; i++) + { + int r = i + uniform(N - i); // between i and N-1 + Object temp = a[i]; + a[i] = a[r]; + a[r] = temp; + } + } + /** + * Rearranges the elements of the specified array in uniformly random order. + * + * @param a the array to shuffle + * @throws NullPointerException if a is null + */ + public static void shuffle(double[] a) + { + if (a == null) + throw new NullPointerException("argument array is null"); + int N = a.length; + for (int i = 0; i < N; i++) + { + int r = i + uniform(N - i); // between i and N-1 + double temp = a[i]; + a[i] = a[r]; + a[r] = temp; + } + } + /** + * Rearranges the elements of the specified array in uniformly random order. + * + * @param a the array to shuffle + * @throws NullPointerException if a is null + */ + public static void shuffle(int[] a) + { + if (a == null) + throw new NullPointerException("argument array is null"); + int N = a.length; + for (int i = 0; i < N; i++) + { + int r = i + uniform(N - i); // between i and N-1 + int temp = a[i]; + a[i] = a[r]; + a[r] = temp; + } + } + /** + * Rearranges the elements of the specified subarray in uniformly random order. + * + * @param a the array to shuffle + * @param lo the left endpoint (inclusive) + * @param hi the right endpoint (inclusive) + * @throws NullPointerException if a is null + * @throws IndexOutOfBoundsException unless (0 <= lo) && (lo <= hi) && (hi < a.length) + * + */ + public static void shuffle(Object[] a, int lo, int hi) + { + if (a == null) + throw new NullPointerException("argument array is null"); + if (lo < 0 || lo > hi || hi >= a.length) { throw new IndexOutOfBoundsException("Illegal subarray range"); } + for (int i = lo; i <= hi; i++) + { + int r = i + uniform(hi - i + 1); // between i and hi + Object temp = a[i]; + a[i] = a[r]; + a[r] = temp; + } + } + /** + * Rearranges the elements of the specified subarray in uniformly random order. + * + * @param a the array to shuffle + * @param lo the left endpoint (inclusive) + * @param hi the right endpoint (inclusive) + * @throws NullPointerException if a is null + * @throws IndexOutOfBoundsException unless (0 <= lo) && (lo <= hi) && (hi < a.length) + */ + public static void shuffle(double[] a, int lo, int hi) + { + if (a == null) + throw new NullPointerException("argument array is null"); + if (lo < 0 || lo > hi || hi >= a.length) { throw new IndexOutOfBoundsException("Illegal subarray range"); } + for (int i = lo; i <= hi; i++) + { + int r = i + uniform(hi - i + 1); // between i and hi + double temp = a[i]; + a[i] = a[r]; + a[r] = temp; + } + } + /** + * Rearranges the elements of the specified subarray in uniformly random order. + * + * @param a the array to shuffle + * @param lo the left endpoint (inclusive) + * @param hi the right endpoint (inclusive) + * @throws NullPointerException if a is null + * @throws IndexOutOfBoundsException unless (0 <= lo) && (lo <= hi) && (hi < a.length) + */ + public static void shuffle(int[] a, int lo, int hi) + { + if (a == null) + throw new NullPointerException("argument array is null"); + if (lo < 0 || lo > hi || hi >= a.length) { throw new IndexOutOfBoundsException("Illegal subarray range"); } + for (int i = lo; i <= hi; i++) + { + int r = i + uniform(hi - i + 1); // between i and hi + int temp = a[i]; + a[i] = a[r]; + a[r] = temp; + } + } + /** + * Unit test. + */ + public static void main(String[] args) + { + int N = Integer.parseInt(args[0]); + if (args.length == 2) + StdRandom.setSeed(Long.parseLong(args[1])); + double[] t = {.5, .3, .1, .1}; + StdOut.println("seed = " + StdRandom.getSeed()); + for (int i = 0; i < N; i++) + { + StdOut.printf("%2d ", uniform(100)); + StdOut.printf("%8.5f ", uniform(10.0, 99.0)); + StdOut.printf("%5b ", bernoulli(.5)); + StdOut.printf("%7.5f ", gaussian(9.0, .2)); + StdOut.printf("%2d ", discrete(t)); + StdOut.println(); + } + String[] a = "A B C D E F G".split(" "); + for (String s : a) + StdOut.print(s + " "); + StdOut.println(); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PizzaUtils/Pizza.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PizzaUtils/Pizza.java new file mode 100644 index 00000000..49f615cd --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PizzaUtils/Pizza.java @@ -0,0 +1,84 @@ +package src.main.java.org.teachingextentions.logo.utils.PizzaUtils; + +import java.util.ArrayList; + +/** + * A slice of pizza + * The Pizza allows you to make different sizes and kinds of pizza! + */ +public class Pizza +{ + private ArrayList toppings = new ArrayList(); + private boolean cooked; + private int slices = 2; + /** + * Adds a topping to a pizza + *

Example: {@code pizza.addTopping(Topping.Spam)}
+ * + * @param topping A topping from the list + */ + public void addTopping(Topping topping) + { + this.toppings.add(topping); + } + /** + * Checks to see if a pizza has a particular kind of topping + *
Example: {@code pizza.hasTopping(topping)}
+ * + * @param topping A topping from the list to check for + * @return true when the pizza has the topping on it + */ + public boolean hasTopping(Topping topping) + { + for (Topping toppingToday : toppings) + { + if (toppingToday == topping) { return true; } + } + return false; + } + /** + * Cooks a pizza + *
Example: {@code pizza.cook()}
+ */ + public void cook() + { + this.cooked = true; + } + /** + * Checks whether a pizza was cooked + *
Example: {@code pizza.wasCooked()}
+ * + * @return whether or not the pizza has been cooked already + */ + public boolean wasCooked() + { + return this.cooked; + } + public void ____() + { + } + /** + * Checks whether you can take a slice of pizza or not + *
Example: {@code pizza.takeSlice()}
+ * + * @return whether or not the pizza has any more slices to take + * If there are still slices, takes one slice + */ + public boolean takeSlice() + { + if (0 < this.slices) + { + this.slices--; + return true; + } + return false; + } + /** + * Adds more slices to a pizza + *
Example: {@code pizza.superSizeIt()}
+ */ + public void superSizeIt() + { + this.slices = 8; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PizzaUtils/Topping.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PizzaUtils/Topping.java new file mode 100644 index 00000000..d1d45e72 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PizzaUtils/Topping.java @@ -0,0 +1,5 @@ +package src.main.java.org.teachingextentions.logo.utils.PizzaUtils; + +public enum Topping { + NoTopping, Pepperoni, Anchovy, Cheese, Spam, Broccoli +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/AStarEstimator.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/AStarEstimator.java new file mode 100644 index 00000000..9c780312 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/AStarEstimator.java @@ -0,0 +1,16 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.util.Comparator; + +public class AStarEstimator implements Comparator +{ + @Override + public int compare(PuzzleState left, PuzzleState right) + { + return costOf(left) - costOf(right); + } + private int costOf(PuzzleState state) + { + return state.getActualCost() + state.getEstimatedCost(); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/AStarPlayer.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/AStarPlayer.java new file mode 100644 index 00000000..46a75186 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/AStarPlayer.java @@ -0,0 +1,15 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.util.PriorityQueue; + +/** + * A player who solves puzzles using the A* strategy will not only take into account the known cost of a reaching + * a puzzle state, but also estimates the remaining cost to the goal. + */ +public class AStarPlayer extends PuzzlePlayer +{ + public AStarPlayer(Puzzle puzzle) + { + super(puzzle, new PriorityQueue<>(1, new AStarEstimator())); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/BreadthFirstPlayer.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/BreadthFirstPlayer.java new file mode 100644 index 00000000..2f89a24a --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/BreadthFirstPlayer.java @@ -0,0 +1,14 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.util.ArrayDeque; + +/** + * A player who solves puzzles using breadth-first search. + */ +public class BreadthFirstPlayer extends PuzzlePlayer +{ + public BreadthFirstPlayer(Puzzle puzzle) + { + super(puzzle, new ArrayDeque()); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/Puzzle.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/Puzzle.java new file mode 100644 index 00000000..10002b90 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/Puzzle.java @@ -0,0 +1,121 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.awt.Point; +import java.util.Arrays; + +/** + * A nine-puzzle + * + * @see Wikipedia + */ +public class Puzzle +{ + private static final int blank = 8; + private final int[] cells; + public Puzzle(int[] cells) + { + this.cells = cells; + } + /** + * Gives the position of the cell as it would appear on a 3x3 board. + * + * @param cell + * The cell to get the position for. + * @return The position of the cell. + */ + public static Point getPosition(int cell) + { + return new Point(cell % 3, cell / 3); + } + /** + * Calculate the Manhattan Distance between two positions. + * + * @param start + * The starting position. + * @param end + * The ending position. + * @return The distance between the two positions. + */ + public static int getDistance(Point start, Point end) + { + return Math.abs(start.x - end.x) + Math.abs(start.y - end.y); + } + /** + * Calculate the Manhattan Distance between two cells by first converting them to positions. + * + * @param start + * The starting cell + * @param end + * The ending cell + * @return The distance between the cells. + */ + public static int getDistance(int start, int end) + { + return getDistance(getPosition(start), getPosition(end)); + } + @Override + public int hashCode() + { + return Arrays.hashCode(cells); + } + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Puzzle puzzle = (Puzzle) o; + return Arrays.equals(cells, puzzle.cells); + } + @Override + public String toString() + { + return Arrays.toString(cells); + } + public boolean isSolved() + { + return getDistanceToGoal() == 0; + } + public int getBlankIndex() + { + for (int i = 0; i < cells.length; i++) + { + if (cells[i] == blank) { return i; } + } + return -1; + } + /** + * Create a copy of the puzzle where the blank swapped with the value in the target position + * + * @param target + * move the blank to this location, and move the value from this location to the current blank location + * @return A copy of the puzzle with the blank and target swapped. + */ + public Puzzle swapBlank(int target) + { + int[] copy = Arrays.copyOf(cells, cells.length); + int x = copy[target]; + copy[getBlankIndex()] = x; + copy[target] = 8; + return new Puzzle(copy); + } + /** + * Calculate the distance between the goal by summing the distance between each cell and its goal. + * + * @return The distance to the goal. + */ + public int getDistanceToGoal() + { + int distance = 0; + for (int i = 0; i < cells.length; i++) + { + distance += getDistance(i, cells[i]); + } + return distance; + } + public int[] getCells() + { + return Arrays.copyOf(cells, cells.length); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleAnimation.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleAnimation.java new file mode 100644 index 00000000..a0d305b3 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleAnimation.java @@ -0,0 +1,65 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import javax.swing.SwingUtilities; + +/** + * Animates a puzzle from its initial state to its solution. + */ +public class PuzzleAnimation implements Runnable +{ + private final PuzzleBoard board; + public PuzzleAnimation(PuzzleBoard board) + { + this.board = board; + } + private static void update(PuzzleBoard board) + { + boolean done = animate(board); + if (!done) { return; } + moveNextTile(board); + } + private static void moveNextTile(PuzzleBoard board) + { + if (board.hasMoves()) + { + TileMove move = board.getNextMove(); + board.swap(move.getStart(), move.getEnd()); + } + } + private static boolean animate(PuzzleBoard board) + { + Tile[] tiles = board.getTiles(); + for (Tile tile : tiles) + { + if (tile != null && !tile.isAtTarget()) + { + tile.step(); + return false; + } + } + return true; + } + @Override + public void run() + { + while (board.isVisible()) + { + SwingUtilities.invokeLater(new Runnable() + { + @Override + public void run() + { + board.repaint(); + } + }); + update(board); + try + { + Thread.sleep(10); + } + catch (InterruptedException ignored) + { + } + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleBoard.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleBoard.java new file mode 100644 index 00000000..d12b780b --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleBoard.java @@ -0,0 +1,120 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Queue; + +import javax.swing.JPanel; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.StringUtils; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.TkpPanel; + +/** + * Draws and animates a 9-puzzle + */ +public class PuzzleBoard extends JPanel +{ + private static final long serialVersionUID = -2008156268412728375L; + private final static int blank = 8; + private final Tile[] tiles; + private final Queue solution; + public PuzzleBoard(final Puzzle puzzle, final PuzzleState solution) + { + super(); + this.solution = createSolution(solution, puzzle); + this.tiles = createTiles(puzzle.getCells()); + } + public static Queue createSolution(final PuzzleState solution, final Puzzle puzzle) + { + if (solution == null) { return new ArrayDeque<>(); } + int i = puzzle.getBlankIndex(); + final Queue moves = new ArrayDeque<>(); + for (final PuzzleState.Direction d : solution.getHistory()) + { + final int m = d.getValue(); + final TileMove move = new TileMove(i + m, i); + moves.add(move); + i = move.getStart(); + } + return moves; + } + private static Tile[] createTiles(final int[] cells) + { + final Tile[] t = new Tile[9]; + for (int i = 0; i < 9; i++) + { + if (cells[i] == blank) + { + continue; + } + t[i] = new Tile(i, cells[i]); + } + return t; + } + private static void drawBorder(final Graphics2D g) + { + g.setColor(PenColors.Blues.DarkBlue); + g.fillRect(20, 20, 410, 410); + } + private static void drawField(final Graphics2D g) + { + g.setColor(PenColors.Blues.SkyBlue); + g.fillRect(30, 30, 386, 386); + } + private static void drawTiles(final Graphics2D g, final Tile[] tiles) + { + for (final Tile tile : tiles) + { + if (tile == null) + { + continue; + } + tile.paint(g); + } + } + @Override + protected void paintComponent(final Graphics g) + { + super.paintComponent(g); + final Graphics2D g2d = TkpPanel.configureGraphics2D(g); + drawBorder(g2d); + drawField(g2d); + drawTiles(g2d, tiles); + g2d.dispose(); + } + public Tile[] getTiles() + { + return Arrays.copyOf(tiles, tiles.length); + } + public boolean hasMoves() + { + return !solution.isEmpty(); + } + public TileMove getNextMove() + { + return solution.isEmpty() ? null : solution.remove(); + } + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append("PuzzleBoard" + StringUtils.NEW_LINE); + for (int i = 0; i < tiles.length; i += 3) + { + sb.append(tiles[i] + ", " + tiles[i + 1] + ", " + tiles[i + 2] + StringUtils.NEW_LINE); + } + return sb.toString(); + } + public void swap(final int start, final int end) + { + final Point p = Tile.getPosition(end); + final Tile tile = tiles[start]; + tile.moveTo(p); + tiles[start] = null; + tiles[end] = tile; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzlePlayer.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzlePlayer.java new file mode 100644 index 00000000..373fb676 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzlePlayer.java @@ -0,0 +1,60 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.util.HashSet; +import java.util.List; +import java.util.Queue; +import java.util.Set; + +/** + * A player solves puzzles using a certain style. + */ +public abstract class PuzzlePlayer +{ + private final Puzzle puzzle; + private final Set visited = new HashSet<>(); + private final Queue frontier; + public PuzzlePlayer(Puzzle puzzle, Queue frontier) + { + this.puzzle = puzzle; + this.frontier = frontier; + } + protected Set getVisited() + { + return visited; + } + protected Queue getFrontier() + { + return frontier; + } + protected Puzzle getPuzzle() + { + return puzzle; + } + public PuzzleState solve() + { + PuzzleState state = new PuzzleState(this.getPuzzle()); + do + { + getVisited().add(state); + if (!state.isSolution()) + { + this.search(state); + if (getFrontier().isEmpty()) { throw new IllegalStateException("Cannot solve puzzle."); } + state = getFrontier().remove(); + } + } + while (!state.isSolution()); + return state; + } + protected void search(PuzzleState state) + { + List branches = state.getBranches(); + for (PuzzleState b : branches) + { + if (!getVisited().contains(b)) + { + getFrontier().add(b); + } + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleState.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleState.java new file mode 100644 index 00000000..4e01d43c --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleState.java @@ -0,0 +1,130 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Stack; + +/** + * Represents a node in the puzzle-solving graph. Keeps track of the current puzzle arrangement and the actions + * required to arrive at the current arrangement from the starting arrangement. + */ +public class PuzzleState implements Comparator, Comparable +{ + private final Puzzle puzzle; + private final Stack history; + public PuzzleState(Puzzle puzzle) + { + this(puzzle, new Stack()); + } + public PuzzleState(Puzzle puzzle, Stack history) + { + this.puzzle = puzzle; + this.history = history; + } + public boolean isSolution() + { + return puzzle.isSolved(); + } + public List getBranches() + { + List branches = new ArrayList<>(4); + int blank = puzzle.getBlankIndex(); + int x = blank % 3; + int y = blank / 3; + for (Direction d : Direction.values()) + { + if (d == Direction.Left && x == 0) + { + continue; + } + if (d == Direction.Right && x == 2) + { + continue; + } + if (d == Direction.Up && y == 0) + { + continue; + } + if (d == Direction.Down && y == 2) + { + continue; + } + Stack h = new Stack<>(); + h.addAll(history); + h.push(d); + branches.add(new PuzzleState(puzzle.swapBlank(blank + d.getValue()), h)); + } + return branches; + } + public Iterable getHistory() + { + return this.history; + } + public Puzzle getPuzzle() + { + return this.puzzle; + } + public int getActualCost() + { + return this.history.size(); + } + @Override + public int compare(PuzzleState o1, PuzzleState o2) + { + return o1.getActualCost() - o2.getActualCost(); + } + @Override + public int compareTo(PuzzleState o) + { + return compare(this, o); + } + @Override + public int hashCode() + { + return puzzle.hashCode(); + } + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + PuzzleState that = (PuzzleState) o; + return puzzle.equals(that.puzzle); + } + @Override + public String toString() + { + StringBuilder b = new StringBuilder(); + if (!history.isEmpty()) + { + b.append(history.peek()); + b.append(" to "); + } + b.append(puzzle); + return b.toString(); + } + public int getEstimatedCost() + { + return puzzle.getDistanceToGoal(); + } + public enum Direction { + Left(-1), Right(1), Up(-3), Down(3); + private final int value; + private Direction(int i) + { + this.value = i; + } + public int getValue() + { + return value; + } + @Override + public String toString() + { + return "{" + super.toString() + " = " + value + '}'; + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleWindow.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleWindow.java new file mode 100644 index 00000000..d4bbaffd --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/PuzzleWindow.java @@ -0,0 +1,21 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.ProgramWindow; +import java.awt.*; + +/** + * A program window for a 9-puzzle + */ +public class PuzzleWindow extends ProgramWindow +{ + public PuzzleWindow() + { + super("Puzzle"); + this.getCanvas().setLayout(new BorderLayout()); + } + public PuzzleWindow(PuzzleBoard board) + { + this(); + this.getCanvas().add(board); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/Tile.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/Tile.java new file mode 100644 index 00000000..2331200d --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/Tile.java @@ -0,0 +1,72 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Point; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; + +/** + * A tile is a square on the board with an image on it. + */ +public class Tile +{ + private static final String[] resources = {"Batgirl1a.png", + "Batgirl2a.png", + "Batgirl3a.png", + "Batgirl1b.png", + "Batgirl2b.png", + "Batgirl3b.png", + "Batgirl1c.png", + "Batgirl2c.png", + "Batgirl3c.png" }; + private static final Point origin = new Point(35, 35); + private final Image image; + private final Dimension dimension = new Dimension(122, 122); + private Point position; + private Point target; + public Tile(int cell, int image) + { + this.position = getPosition(cell); + this.image = getImage(image); + } + public static Point getPosition(int cell) + { + Point offset = Puzzle.getPosition(cell); + return new Point(origin.x + (127 * offset.x), origin.y + (127 * offset.y)); + } + private static Image getImage(int image) + { + return ObjectUtils.loadImage(Tile.class, resources[image]); + } + private static int stepTowardGoal(int current, int goal) + { + if (current < goal) { return current + 1; } + if (goal < current) { return current - 1; } + return current; + } + public void paint(Graphics2D g2d) + { + g2d.drawImage(this.image, this.position.x, this.position.y, this.dimension.width, this.dimension.height, null); + } + public boolean isAtTarget() + { + return target == null || (target.x == position.x && target.y == position.y); + } + public void step() + { + int x = stepTowardGoal(position.x, target.x); + int y = stepTowardGoal(position.y, target.y); + this.position = new Point(x, y); + } + public void moveTo(Point goal) + { + target = goal; + } + @Override + public String toString() + { + return "Tile{" + position.x + ", " + position.y + '}'; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/TileMove.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/TileMove.java new file mode 100644 index 00000000..1fac3dfa --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/TileMove.java @@ -0,0 +1,28 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +/** + * Describes a tile swap. + */ +public class TileMove +{ + private final int start; + private final int end; + public TileMove(int start, int end) + { + this.start = start; + this.end = end; + } + @Override + public String toString() + { + return "TileMove{" + "start=" + start + ", end=" + end + '}'; + } + public int getStart() + { + return start; + } + public int getEnd() + { + return end; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/UniformCostPlayer.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/UniformCostPlayer.java new file mode 100644 index 00000000..175d7aa6 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/PuzzleUtils/UniformCostPlayer.java @@ -0,0 +1,15 @@ +package src.main.java.org.teachingextentions.logo.utils.PuzzleUtils; + +import java.util.PriorityQueue; + +/** + * Uniform cost player tries to pick the solution with the least number of steps. The player treats every step as + * if to costs the same as any other step. + */ +public class UniformCostPlayer extends PuzzlePlayer +{ + public UniformCostPlayer(Puzzle puzzle) + { + super(puzzle, new PriorityQueue()); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/SetupUtils/CommandLineUtils.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/SetupUtils/CommandLineUtils.java new file mode 100644 index 00000000..a51c6dcd --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/SetupUtils/CommandLineUtils.java @@ -0,0 +1,16 @@ +package src.main.java.org.teachingextentions.logo.utils.SetupUtils; + +import java.io.IOException; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; + +public class CommandLineUtils { + public static void launch(String commandLine, String... formattingArguments) { + try { + String command = String.format(commandLine, + (Object[]) formattingArguments); + Runtime.getRuntime().exec(command); + } catch (IOException e) { + ObjectUtils.throwAsError(e); + } + } +} diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/MakeALogo.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TKPLogoUtils/MakeALogo.java similarity index 84% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/MakeALogo.java rename to TKPJava/src/main/java/org/teachingextentions/logo/utils/TKPLogoUtils/MakeALogo.java index 7f4fe6b0..18136fe7 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/MakeALogo.java +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TKPLogoUtils/MakeALogo.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section01forloops; +package src.main.java.org.teachingextentions.logo.utils.TKPLogoUtils; public class MakeALogo { diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/TKPLogoUtils/TKPLogo.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TKPLogoUtils/TKPLogo.java new file mode 100644 index 00000000..a444a084 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TKPLogoUtils/TKPLogo.java @@ -0,0 +1,290 @@ +package src.main.java.org.teachingextentions.logo.utils.TKPLogoUtils; + +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.ColorWheel; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; + +/** + * The TKP logo + * The TKPLogo allows you to create a super cool TKP logo on your window + */ +public class TKPLogo +{ + /** + * Sets up a particular set of Colors on the Color Wheel + *
Example: {@code TKPLogo.setupColorWheel();}
+ */ + public static void setupColorWheel() + { + ColorWheel.addColor(PenColors.Grays.Gray); + ColorWheel.addColor(PenColors.Greens.Green); + ColorWheel.addColor(PenColors.Pinks.Pink); + ColorWheel.addColor(PenColors.Purples.Purple); + ColorWheel.addColor(PenColors.Blues.Blue); + ColorWheel.addColor(PenColors.Yellows.Yellow); + ColorWheel.addColor(PenColors.Browns.Brown); + ColorWheel.addColor(PenColors.Oranges.Orange); + ColorWheel.addColor(PenColors.Reds.Red); + ColorWheel.addColor(PenColors.Whites.White); + setupBackgroundAndLines(); + } + private static void setupBackgroundAndLines() + { + Tortoise.getBackgroundWindow() + .setBackground(ColorWheel.getRandomColorFromWheel()); + Tortoise.setPenWidth(4); + } + /** + * Draws an amazing TKP inner P + *
Example: {@code TKPLogo.draw_inner_tkp_P();}
+ */ + public static void draw_inner_tkp_P() + { + Tortoise.setX(MakeALogo.XValue + 355); + Tortoise.setY(MakeALogo.YValue - 135); + Tortoise.turn(180); + Tortoise.move(10); + TKPLogo.curve6(); + Tortoise.move(10); + Tortoise.turn(90); + Tortoise.move(50); + Tortoise.hide(); + Tortoise.turn(1); + } + /** + * Draws an awesome TKP outer P + *
Example: {@code TKPLogo.draw_outer_tkp_P();}
+ */ + public static void draw_outer_tkp_P() + { + Tortoise.setAngle(180); + Tortoise.setX(MakeALogo.XValue + 320); + Tortoise.setY(MakeALogo.YValue); + Tortoise.turn(180); + Tortoise.move(15); + Tortoise.turn(80); + Tortoise.move(10); + Tortoise.turn(-80); + Tortoise.move(120); + Tortoise.turn(-80); + Tortoise.move(10); + Tortoise.turn(80); + Tortoise.move(15); + Tortoise.turn(90); + Tortoise.move(47); + TKPLogo.curve5(); + Tortoise.move(12); + Tortoise.turn(-90); + Tortoise.move(50); + Tortoise.turn(-80); + Tortoise.move(10); + Tortoise.turn(80); + Tortoise.move(15); + Tortoise.turn(90); + Tortoise.move(43); + } + /** + * Draws an outstanding TKP right bracket + *
Example: {@code TKPLogo.drawRightBracket();}
+ */ + public static void drawRightBracket() + { + Tortoise.setAngle(-90); + Tortoise.setX(MakeALogo.XValue + 250); + Tortoise.setY(MakeALogo.YValue - 20); + Tortoise.turn(180); + Tortoise.move(30); + TKPLogo.curve3(); + Tortoise.move(40); + TKPLogo.curve4(); + Tortoise.move(10); + Tortoise.turn(-90); + Tortoise.move(10); + Tortoise.turn(-90); + Tortoise.move(10); + TKPLogo.curve4(); + Tortoise.move(40); + TKPLogo.curve3(); + Tortoise.move(30); + Tortoise.turn(-90); + Tortoise.move(10); + Tortoise.turn(-90); + Tortoise.move(15); + TKPLogo.curve1(); + Tortoise.move(35); + TKPLogo.curve2(); + Tortoise.turn(180); + TKPLogo.curve2(); + Tortoise.move(35); + TKPLogo.curve1(); + Tortoise.move(15); + Tortoise.turn(-90); + Tortoise.move(11); + } + /** + * Draws an original TKP left bracket + *
Example: {@code TKPLogo.drawLeftBracket();}
+ */ + public static void drawLeftBracket() + { + Tortoise.setAngle(-90); + Tortoise.setX(MakeALogo.XValue + 130); + Tortoise.setY(MakeALogo.YValue - 20); + Tortoise.move(30); + TKPLogo.curve1(); + Tortoise.move(40); + TKPLogo.curve2(); + Tortoise.move(10); + Tortoise.turn(90); + Tortoise.move(10); + Tortoise.turn(90); + Tortoise.move(10); + TKPLogo.curve2(); + Tortoise.move(40); + TKPLogo.curve1(); + Tortoise.move(30); + Tortoise.turn(90); + Tortoise.move(10); + Tortoise.turn(90); + Tortoise.move(15); + TKPLogo.curve3(); + Tortoise.move(35); + TKPLogo.curve4(); + Tortoise.turn(180); + TKPLogo.curve4(); + Tortoise.move(35); + TKPLogo.curve3(); + Tortoise.move(15); + Tortoise.turn(90); + Tortoise.move(10); + } + /** + * Draws an incredible TKP T + *
Example: {@code TKPLogo.draw_tkp_T();}
+ */ + public static void draw_tkp_T() + { + Tortoise.setX(MakeALogo.XValue); + Tortoise.setY(MakeALogo.YValue); + Tortoise.move(15); + Tortoise.turn(80); + Tortoise.move(10); + Tortoise.turn(-80); + Tortoise.move(120); + Tortoise.turn(-90); + Tortoise.move(15); + Tortoise.turn(-75); + Tortoise.move(10); + Tortoise.turn(75); + Tortoise.move(15); + Tortoise.turn(90); + Tortoise.move(35); + Tortoise.turn(90); + Tortoise.move(95); + Tortoise.turn(90); + Tortoise.move(35); + Tortoise.turn(90); + Tortoise.move(15); + Tortoise.turn(75); + Tortoise.move(10); + Tortoise.turn(-75); + Tortoise.move(15); + Tortoise.turn(-90); + Tortoise.move(120); + Tortoise.turn(-80); + Tortoise.move(10); + Tortoise.turn(80); + Tortoise.move(15); + Tortoise.turn(90); + Tortoise.move(50); + } + /** + * Draws an impressive TKP K + *
Example: {@code TKPLogo.draw_tkp_K();}
+ */ + public static void draw_tkp_K() + { + Tortoise.setAngle(180); + Tortoise.setX(MakeALogo.XValue + 150); + Tortoise.setY(MakeALogo.YValue + 15); + Tortoise.turn(180); + Tortoise.move(200); + Tortoise.turn(90); + Tortoise.move(30); + Tortoise.turn(90); + Tortoise.move(128); + Tortoise.turn(-150); + Tortoise.move(70); + Tortoise.turn(90); + Tortoise.move(30); + Tortoise.turn(90); + Tortoise.move(70); + Tortoise.turn(-80); + Tortoise.move(80); + Tortoise.turn(140); + Tortoise.move(40); + Tortoise.turn(40); + Tortoise.move(60); + Tortoise.turn(-130); + Tortoise.move(45); + Tortoise.turn(90); + Tortoise.move(30); + Tortoise.turn(2); + } + private static void curve6() + { + for (int i = 0; i < 180; i++) + { + double size = 0.43; + Tortoise.turn(1); + Tortoise.move(size); + } + } + private static void curve5() + { + for (int i = 0; i < 180; i++) + { + double size = 0.75; + Tortoise.turn(1); + Tortoise.move(size); + Tortoise.move(-size); + Tortoise.move(size); + } + } + private static void curve4() + { + for (int i = 0; i < 90; i++) + { + double size = 0.15; + Tortoise.turn(1); + Tortoise.move(size); + } + } + private static void curve2() + { + for (int i = 0; i < 90; i++) + { + double size = 0.15; + Tortoise.turn(-1); + Tortoise.move(size); + } + } + private static void curve1() + { + for (int i = 0; i < 90; i++) + { + double size = 0.25; + Tortoise.turn(1); + Tortoise.move(size); + } + } + private static void curve3() + { + for (int i = 0; i < 90; i++) + { + double size = 0.25; + Tortoise.turn(-1); + Tortoise.move(size); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/MultiTurtleWindow.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/MultiTurtleWindow.java new file mode 100644 index 00000000..dabd1c13 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/MultiTurtleWindow.java @@ -0,0 +1,83 @@ +package src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils; + +import java.util.ArrayList; +import java.util.List; + +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.MultiTurtlePainter; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.MultiTurtleTrailPainter; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.TurtleFrame; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; + +/** + * Use this window when you want to put more than one turtle on the same window + */ +public class MultiTurtleWindow extends TurtleWindow +{ + private List turtles = new ArrayList(); + public MultiTurtleWindow() + { + super("Turtles, Turtles, Turtles!"); + this.setBackground(PenColors.Blues.DarkSlateBlue); + } + /** + * Adds a turtle instance to a window + * NOTE: this method must be called BEFORE calling any other methods on turtle instances + *

Example: {@code multiTurtleWindow.addTurtle(myTurtle)}

+ * + * @param turtle + * A turtle instance + */ + public void addTurtle(Turtle turtle) + { + if (turtle == null) { return; } + turtle.setFrame(this.getFrame()); + turtle.setPanel(this); + this.turtles.add(turtle); + clearPainters(); + configurePainters(); + } + @Override + public TurtleWindow init(Turtle turtle, TurtleFrame frame) + { + return this; + } + @Override + protected Paintable createTurtleTrailPainter() + { + this.setTrailPainter(new MultiTurtleTrailPainter(this.turtles)); + return this.getTrailPainter(); + } + @Override + protected Paintable createTurtlePainter() + { + this.setTurtlePainter(new MultiTurtlePainter(this.turtles, this.getImage())); + return this.getTurtlePainter(); + } + /** + * Gets a count of turtles for a window + *

Example: {@code multiTurtleWindow.getTurtlesCount()}

+ * + */ + public int getTurtleCount() + { + return this.turtles.size(); + } + /** + * Adds a turtle instance to a window and shows it on the window + *

Example: {@code multiTurtleWindow.addAndShowTurtle(myTurtle)}

+ * + * @param turtle + * A turtle instance + */ + public void addAndShowTurtle(Turtle turtle) + { + this.addTurtle(turtle); + this.showTurtle(turtle); + } + private void showTurtle(Turtle turtle) + { + turtle.show(); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/ProgramWindow.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/ProgramWindow.java new file mode 100644 index 00000000..d84fedc6 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/ProgramWindow.java @@ -0,0 +1,210 @@ +package src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.event.MouseListener; +import java.awt.image.BufferedImage; + +import javax.swing.JButton; +import javax.swing.JFrame; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.FrameCloser; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.WindowUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ComponentApprovalWriter; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.LeftClickMouseAdapter; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.MouseLeftClickListener; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.MouseRightClickListener; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.RightClickMouseAdapter; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.CanvasPanel; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.TurtleFrame; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.ImageBackground; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.utils.VirtualProctorUtils.VirtualProctorWeb; + +/** + * A window image Program Window + * allows you to change the color of the background and more... + */ +public class ProgramWindow +{ + private final LazyCanvas canvas = new LazyCanvas(); + private JFrame frame; + public ProgramWindow(String title) + { + this(); + this.frame = new JFrame(title); + this.canvas.addTo(this.frame); + ProgramWindow.createStandardFrame(getFrame()); + } + public ProgramWindow() + { + this.canvas.setPreferredSize(new Dimension(627, 442)); + setColor(PenColors.Whites.White); + } + public static void createStandardFrame(JFrame frame) + { + WindowUtils.testFrame(frame, new VirtualProctorWeb(), new FrameCloser()); + } + /** + * Adds a button instance to a window + *

Example: {@code programWindow.addButton(myButton)}

+ * + * @param button + * A button instance + */ + public void addButton(JButton button) + { + this.canvas.add(button); + } + public void setColor(Color backgroundColor) + { + this.canvas.setBackground(backgroundColor); + } + public ProgramWindow clearWindow() + { + this.canvas.clear(); + return this; + } + /** + * Adds a right mouse click listener instance to a window + *

Example: {@code programWindow.addMouseRightClickListener(myRightClickListener)}

+ * + * @param listener + * A listener instance + */ + public void addMouseRightClickListener(MouseRightClickListener listener) + { + this.canvas.addMouseListener(new RightClickMouseAdapter(listener)); + } + /** + * Adds a left mouse click listener instance to a window + *

Example: {@code programWindow.addMouseLeftClickListener(myLeftClickListener)}

+ * + * @param listener + * A listener instance + */ + public void addMouseLeftClickListener(MouseLeftClickListener listener) + { + this.canvas.addMouseListener(new LeftClickMouseAdapter(listener)); + } + /** + * Adds a background image to a window + *

Example: {@code programWindow.setBackgroundImage("http://www.coolpicture.com/sunshine.jpg")}

+ * + * @param url + * A URL path to an image + */ + public void setBackgroundImage(String url) + { + add(new ImageBackground(url)); + } + public JFrame getFrame() + { + return frame; + } + public void setWindowVisible(boolean b) + { + this.frame.setVisible(b); + this.canvas.getValue().setVisible(b); + } + @Deprecated + public ProgramWindow add(Paintable painter) + { + this.canvas.getValue().add(painter); + return this; + } + @Deprecated + public ProgramWindow remove(Paintable painter) + { + this.canvas.getValue().remove(painter); + return this; + } + public final BufferedImage getWindowImage() + { + return ComponentApprovalWriter.drawComponent(this.canvas.getValue()); + } + public ProgramWindow addTo(TurtleFrame frame) + { + frame.addContent(this.canvas.getValue()); + return this; + } + public ProgramWindow repaint() + { + this.canvas.getValue().repaint(); + return this; + } + public ProgramWindow setVisible(boolean visible) + { + this.canvas.getValue().setVisible(visible); + return this; + } + public ProgramWindow setCursor(int cursor) + { + this.setCursor(Cursor.getPredefinedCursor(cursor)); + return this; + } + public ProgramWindow setCursor(Cursor predefinedCursor) + { + this.canvas.getValue().setCursor(predefinedCursor); + return this; + } + public ProgramWindow setBackground(Color color) + { + this.canvas.setBackground(color); + return this; + } + public CanvasPanel getCanvas() + { + return this.canvas.getValue(); + } + private class LazyCanvas + { + private CanvasPanel panel; + public LazyCanvas addTo(JFrame frame) + { + frame.getContentPane().add(this.getValue()); + return this; + } + public CanvasPanel getValue() + { + if (this.panel == null) + { + this.panel = new CanvasPanel(); + } + return panel; + } + public LazyCanvas setPreferredSize(Dimension dimension) + { + this.getValue().setPreferredSize(dimension); + return this; + } + public LazyCanvas add(JButton button) + { + this.getValue().add(button); + return this; + } + public LazyCanvas setBackground(Color color) + { + this.getValue().setBackground(color); + return this; + } + public LazyCanvas clear() + { + this.getValue().clear(); + return this; + } + public LazyCanvas addMouseListener(MouseListener adapter) + { + this.getValue().addMouseListener(adapter); + return this; + } + @SuppressWarnings("unused") + public LazyCanvas setImageBackground(ImageBackground imageBackground) + { + this.getValue().setBackground(imageBackground); + return this; + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/Sound.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/Sound.java new file mode 100644 index 00000000..97266287 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/Sound.java @@ -0,0 +1,85 @@ +package src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils; + +import java.awt.Toolkit; +import java.net.URL; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; + +/** + * A speaker with sound waves + * Sound allows you to play a sound, like a 'beep' or the sound from a file + */ +public class Sound +{ + private URL soundUrl = null; + public Sound() + { + this(TKPSound.Yay); + } + public Sound(TKPSound sound) + { + this.setSound(sound); + } + /** + * Plays a beep through your speakers. BEEP!
+ * Example: {@code Sound.playBeep()} + */ + public static void playBeep() + { + Toolkit.getDefaultToolkit().beep(); + } + /** + * Sets a sound that you can play through your speakers. + * Use a TKPSound (there is a list)
+ * Example: {@code Sound.setSound(TKPSound.Ahem)} + */ + public synchronized void setSound(TKPSound mySound) + { + // NOTE: Fix this path to be relative to correct location + String sound = "soundFiles/" + mySound + ".wav"; + URL resource = this.getClass().getResource(sound); + if (resource == null) + { + resource = this.getClass().getClassLoader().getResource(sound); + } + if (resource == null) { throw new IllegalStateException("Could not get TKPSound: " + sound); } + this.soundUrl = resource; + } + /** + * Plays a TKPSound through your speakers. + * You must first set the TKPSound
+ * Example: {@code Sound.playSound()} + */ + public synchronized void playSound() + { + final URL sound = this.soundUrl; + new Thread(new Runnable() + { + @Override + public void run() + { + try + { + Clip clip = AudioSystem.getClip(); + AudioInputStream inputStream = AudioSystem.getAudioInputStream(sound); + clip.open(inputStream); + clip.start(); + } + catch (Exception e) + { + System.out.println("play sound error: " + e.getMessage() + " for " + sound); + } + } + }).start(); + } + /** + * Check out our cool sounds - thanks to http://www.wavsource.com/ + */ + public enum TKPSound { + Ahem, Applause, BrainIsGone, CatMeow, Cheering, Crickets, DoctorMccoy, Fanfare, FargoYah, + Gong, LLCoolJYaKnow, LosingPower, LoveBeingATurtle, Malfunction, Pizza, RunAway, + SheerIgnorance, SoBeIt, StrangePerson, Stubborn, Yahoo, Yay + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/Turtle.png b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/Turtle.png new file mode 100644 index 00000000..9226aeb0 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/Turtle.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/TurtleWindow.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/TurtleWindow.java new file mode 100644 index 00000000..a56cb77a --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/TurtleWindow.java @@ -0,0 +1,111 @@ +package src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ObjectUtils; +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.Turtle.Animals; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.TurtleFrame; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.TurtlePainter; +import src.main.java.org.teachingextentions.logo.utils.InterfaceUtils.TurtleTrailPainter; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; + +import java.awt.*; + +public class TurtleWindow extends ProgramWindow { + protected Animals animal = Animals.Turtle; + protected Image image; + private Turtle turtle; + private Paintable trailPainter; + private Paintable turtlePainter; + + public TurtleWindow() { + this(null, null); + } + + public TurtleWindow(String title) { + this(title, null); + } + + public TurtleWindow(String title, Turtle turtle) { + super(title); + this.turtle = turtle; + this.image = loadAnimal(); + configurePainters(); + } + + public void setTurtle(Turtle turtle) { + this.turtle = turtle; + clearPainters(); + configurePainters(); + } + + public synchronized Image getImage() { + if (image == null) { + setAnimal(Animals.Turtle); + } + return image; + } + + public synchronized void setAnimal(Animals animal) { + this.animal = animal; + this.image = loadAnimal(); + clearPainters(); + configurePainters(); + } + + public void ___() { + // blank for the DeepDive + } + + protected void clearPainters() { + this.getCanvas().remove(this.trailPainter) + .remove(this.turtlePainter); + } + + protected void configurePainters() { + this.getCanvas().add(createTurtleTrailPainter()) + .add(createTurtlePainter()); + } + + protected Paintable createTurtleTrailPainter() { + return this.trailPainter = new TurtleTrailPainter(this.turtle); + } + + protected Paintable createTurtlePainter() { + return this.turtlePainter = new TurtlePainter(this.turtle, this.getImage()); + } + + protected Image loadAnimal() { + return ObjectUtils.loadImage(TurtleWindow.class, this.animal + ".png"); + } + + protected Paintable getTrailPainter() { + return trailPainter; + } + + protected void setTrailPainter(Paintable trailPainter) { + this.trailPainter = trailPainter; + } + + protected Paintable getTurtlePainter() { + return turtlePainter; + } + + protected void setTurtlePainter(Paintable turtlePainter) { + this.turtlePainter = turtlePainter; + } + + public TurtleWindow init(Turtle turtle, TurtleFrame frame) { + if (this.turtle != null){ + return this; + } + + if (turtle.getSpeed() != Turtle.TEST_SPEED) { + this.addTo(frame); + frame.setStandardLayout(); + } + + this.setTurtle(turtle); + return this; + } +} + diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/soundFiles/Yay.wav b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/soundFiles/Yay.wav new file mode 100644 index 00000000..9555196c Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/logo/utils/TurtleWindowUtils/soundFiles/Yay.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/ScreenCapture.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/ScreenCapture.java new file mode 100644 index 00000000..e770ce96 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/ScreenCapture.java @@ -0,0 +1,30 @@ +package src.main.java.org.teachingextentions.logo.utils.VirtualProctorUtils; + +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; + +public class ScreenCapture +{ + public static BufferedImage getScaledImageOf(Component component, int width, int height) + { + BufferedImage image = src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ComponentApprovalWriter + .drawComponent(component); + return scaleImage(image, width, height); + } + public static BufferedImage scaleImage(BufferedImage image, int width, int height) + { + return toBufferedImage(image.getScaledInstance(width, height, Image.SCALE_SMOOTH)); + } + public static BufferedImage toBufferedImage(Image image) + { + if (image instanceof BufferedImage) { return (BufferedImage) image; } + BufferedImage buffered = new BufferedImage(image.getWidth(null), image.getHeight(null), + BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = buffered.createGraphics(); + graphics.drawImage(image, 0, 0, null); + graphics.dispose(); + return buffered; + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctor.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctor.java new file mode 100644 index 00000000..45617762 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctor.java @@ -0,0 +1,120 @@ +package src.main.java.org.teachingextentions.logo.utils.VirtualProctorUtils; + +import java.io.File; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.StringUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.io.FileUtils; + +/** + * A teacher at a blackboard Virtual + * Proctor allows you to see what all the TKPJava coders are making + */ +public class VirtualProctor +{ + public static class internals + { + private static final String FILE_NAME = ".virtual_proctor.txt"; + private static final String FILE_CLASS_NAME = ".class.virtual_proctor.txt"; + public static String getName() + { + String name = getCustomName(); + if (name == null) + { + name = getComputerName(); + } + if (name == null) + { + name = getUserName(); + } + return name; + } + private static String getCustomName() + { + File file = new File(FILE_NAME); + if (file.exists()) { return FileUtils + .readFileWithSuppressedExceptions(file).trim(); + } + return null; + } + public static String getComputerName() + { + return System.getenv("COMPUTERNAME"); + } + public static String getUserName() + { + return System.getenv("USER"); + } + public static void resetName() + { + File file = new File(FILE_NAME); + if (file.exists()) + { + file.delete(); + } + } + public static void setName(String name) + { + if (StringUtils.isEmpty(name)) { + return; + } + FileUtils.writeFileQuietly(new File(FILE_NAME), name); + } + public static void setClassName(String className) + { + if (StringUtils.isEmpty(className)) { return; } + FileUtils.writeFileQuietly(new File(FILE_CLASS_NAME), className); + } + public static void resetClassName() + { + File file = new File(FILE_CLASS_NAME); + if (file.exists()) + { + file.delete(); + } + } + public static String getClassName() + { + String name = getCustomClassName(); + if (name == null) + { + name = "world"; + } + return name; + } + private static String getCustomClassName() + { + File file = new File(FILE_CLASS_NAME); + if (file.exists()) { return FileUtils.readFileWithSuppressedExceptions(file).trim(); } + return null; + } + public static String getFullName() + { + return getClassName() + "." + getName(); + } + } + /** + * Allows you to set the displayed username in Virtual Proctor + *
Example: {@code VirtualProctor.setName("Grace Hopper")}
+ * + * @param name + * A name that is displayed for the user in the Virtual + * Proctor client + */ + public static void setName(String name) + { + internals.setName(name); + } + /** + * Allows you to set the displayed classroom name in Virtual Proctor + *
Example: {@code VirtualProctor.setClassName("LePort School")}
+ * + * @param className + * A name that is displayed for the student classroom in the Virtual + * Proctor client + */ + public static void setClassName(String className) + { + internals.setClassName(className); + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctorFileSystem.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctorFileSystem.java new file mode 100644 index 00000000..143bdfad --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctorFileSystem.java @@ -0,0 +1,33 @@ +package src.main.java.org.teachingextentions.logo.utils.VirtualProctorUtils; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.ImageIO; + +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.MySystem; + +public class VirtualProctorFileSystem extends WindowAdapter +{ + @Override + public void windowClosing(WindowEvent event) + { + BufferedImage scaled = ScreenCapture.getScaledImageOf(event.getComponent(), 200, 150); + sendImageToDisk(scaled); + } + public void sendImageToDisk(BufferedImage image) + { + try + { + String filename = "C:\\temp\\VirtualProctor.png"; + ImageIO.write(image, "png", new File(filename)); + //TestUtils.displayFile(filename); + } + catch (Exception e) + { + MySystem.warning(e); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctorWeb.java b/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctorWeb.java new file mode 100644 index 00000000..e375ce18 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/logo/utils/VirtualProctorUtils/VirtualProctorWeb.java @@ -0,0 +1,90 @@ +package src.main.java.org.teachingextentions.logo.utils.VirtualProctorUtils; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.MySystem; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ThreadLauncher; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ThreadUtils; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.Action0; + +import javax.imageio.ImageIO; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.URISyntaxException; +import java.net.URL; + +public class VirtualProctorWeb extends WindowAdapter +{ + private boolean finished = false; + @Override + public void windowClosing(WindowEvent event) + { + final BufferedImage scaled = ScreenCapture.getScaledImageOf(event.getComponent(), 200, 150); + ThreadLauncher.launch(new Action0() + { + @Override + public void call() + { + sendImageToWeb(scaled); + finished = true; + } + }); + } + public void sendImageToDisk(BufferedImage image) throws IOException + { + String filename = "C:\\temp\\VirtualProctor.png"; + ImageIO.write(image, "png", new File(filename)); + } + @Override + public void windowClosed(WindowEvent e) + { + while (!finished) + { + ThreadUtils.sleep(50); + } + } + public void sendImageToWeb(BufferedImage image) + { + sendToWeb(image); + } + private void sendToWeb(BufferedImage image) + { + try + { + URL url = new URL("http://steady-fin-94022.appspot.com/screenshots"); + postImageToUrl(image, url); + } + catch (Exception e) + { + MySystem.event(e.getMessage()); + } + } + private void postImageToUrl(BufferedImage image, URL url) throws URISyntaxException, IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpPost uploadFile = new HttpPost(url.toURI()); + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(image, "png", baos); + InputStream is = new ByteArrayInputStream(baos.toByteArray()); + builder + .addBinaryBody("file", is, ContentType.APPLICATION_OCTET_STREAM, VirtualProctor.internals.getFullName()); + HttpEntity multipart = builder.build(); + uploadFile.setEntity(multipart); + HttpResponse response = httpClient.execute(uploadFile); + if (response.getStatusLine().getStatusCode() == 204) + { + MySystem.event("we've got it!"); + } + else + { + MySystem.event("oh no, the internet ate your screenshot!"); + } + } +} diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl.png new file mode 100755 index 00000000..f08d92c1 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1a.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1a.png new file mode 100755 index 00000000..23ca8cab Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1a.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1b.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1b.png new file mode 100755 index 00000000..ae5c30e1 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1b.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1c.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1c.png new file mode 100755 index 00000000..b0c43a00 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl1c.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2a.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2a.png new file mode 100755 index 00000000..0f5aa249 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2a.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2b.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2b.png new file mode 100755 index 00000000..03e45116 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2b.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2c.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2c.png new file mode 100755 index 00000000..84bd8d0c Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl2c.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3a.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3a.png new file mode 100755 index 00000000..c98f247f Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3a.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3b.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3b.png new file mode 100755 index 00000000..df354c3b Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3b.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3c.png b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3c.png new file mode 100755 index 00000000..f6918c74 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Batgirl3c.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/ExplodedTurtle.png b/TKPJava/src/main/java/org/teachingextentions/resources/ExplodedTurtle.png new file mode 100644 index 00000000..0850d196 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/ExplodedTurtle.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Spider.png b/TKPJava/src/main/java/org/teachingextentions/resources/Spider.png new file mode 100644 index 00000000..f5ff6519 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Spider.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Squid.png b/TKPJava/src/main/java/org/teachingextentions/resources/Squid.png new file mode 100644 index 00000000..bf60c16d Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Squid.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/TortoiseCompass.pdf b/TKPJava/src/main/java/org/teachingextentions/resources/TortoiseCompass.pdf new file mode 100644 index 00000000..038a56ad Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/TortoiseCompass.pdf differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Turtle.png b/TKPJava/src/main/java/org/teachingextentions/resources/Turtle.png new file mode 100644 index 00000000..9226aeb0 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Turtle.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/Unicorn.png b/TKPJava/src/main/java/org/teachingextentions/resources/Unicorn.png new file mode 100644 index 00000000..1d53c50e Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/Unicorn.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/0_Keyboard-Shortcuts.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/0_Keyboard-Shortcuts.docx new file mode 100644 index 00000000..ed1f1067 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/0_Keyboard-Shortcuts.docx differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/1_SimpleSquareWorksheet.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/1_SimpleSquareWorksheet.docx new file mode 100644 index 00000000..8d2fd596 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/1_SimpleSquareWorksheet.docx differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/2_HousesWorksheet.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/2_HousesWorksheet.docx new file mode 100644 index 00000000..5c3736e0 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/2_HousesWorksheet.docx differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/3_HiLowWorksheet.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/3_HiLowWorksheet.docx new file mode 100644 index 00000000..77497080 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/3_HiLowWorksheet.docx differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/4_PentagonCrazyWorksheet.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/4_PentagonCrazyWorksheet.docx new file mode 100644 index 00000000..893c7f2b Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/4_PentagonCrazyWorksheet.docx differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/5_TurtleTreeWorksheet.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/5_TurtleTreeWorksheet.docx new file mode 100644 index 00000000..e6813cae Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/5_TurtleTreeWorksheet.docx differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/6_AdLibsWorksheet.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/6_AdLibsWorksheet.docx new file mode 100644 index 00000000..49237717 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/6_AdLibsWorksheet.docx differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/7_SimpleBubbleWorksheet.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/7_SimpleBubbleWorksheet.docx new file mode 100644 index 00000000..f56a4a07 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/7_SimpleBubbleWorksheet.docx differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/documents/8_FizzBuzzWorksheet.docx b/TKPJava/src/main/java/org/teachingextentions/resources/documents/8_FizzBuzzWorksheet.docx new file mode 100644 index 00000000..c777e99b Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/documents/8_FizzBuzzWorksheet.docx differ diff --git a/Graphics/Tortoise.ai b/TKPJava/src/main/java/org/teachingextentions/resources/graphics/Tortoise.ai similarity index 100% rename from Graphics/Tortoise.ai rename to TKPJava/src/main/java/org/teachingextentions/resources/graphics/Tortoise.ai diff --git a/Graphics/Tortoise.png b/TKPJava/src/main/java/org/teachingextentions/resources/graphics/Tortoise.png similarity index 100% rename from Graphics/Tortoise.png rename to TKPJava/src/main/java/org/teachingextentions/resources/graphics/Tortoise.png diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/Heart.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/Heart.png new file mode 100644 index 00000000..d9883035 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/Heart.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/add.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/add.png new file mode 100644 index 00000000..654a9b8d Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/add.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-down.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-down.png new file mode 100644 index 00000000..7b2ee09b Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-down.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-left.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-left.png new file mode 100644 index 00000000..70d7a230 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-left.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-right.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-right.png new file mode 100644 index 00000000..0c6e1569 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-right.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-up.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-up.png new file mode 100644 index 00000000..06983c51 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/arrow-up.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/bigStar.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/bigStar.png new file mode 100644 index 00000000..d6f05353 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/bigStar.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/bluePhone.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/bluePhone.png new file mode 100644 index 00000000..becc710a Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/bluePhone.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/check.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/check.png new file mode 100644 index 00000000..ff71e24d Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/check.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/checkeredFlag.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/checkeredFlag.png new file mode 100644 index 00000000..68ab1e7f Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/checkeredFlag.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/github.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/github.png new file mode 100644 index 00000000..3c1f4605 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/github.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/greenPhone.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/greenPhone.png new file mode 100644 index 00000000..b0bbd706 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/greenPhone.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/hint.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/hint.png new file mode 100644 index 00000000..face71a5 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/hint.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/information.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/information.png new file mode 100644 index 00000000..20cbd0bd Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/information.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/like.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/like.png new file mode 100644 index 00000000..bf5d1f10 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/like.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/redPhone.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/redPhone.png new file mode 100644 index 00000000..4b64f104 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/redPhone.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/star.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/star.png new file mode 100644 index 00000000..46ff1f83 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/star.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/stop.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/stop.png new file mode 100644 index 00000000..548e3915 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/stop.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/thumb-up.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/thumb-up.png new file mode 100644 index 00000000..ba578aea Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/thumb-up.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/turtleNinja.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/turtleNinja.png new file mode 100644 index 00000000..54c14666 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/turtleNinja.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/icons/yellowPhone.png b/TKPJava/src/main/java/org/teachingextentions/resources/icons/yellowPhone.png new file mode 100644 index 00000000..04a22b8c Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/icons/yellowPhone.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/mazeBackground/CoolMazeBackground.png b/TKPJava/src/main/java/org/teachingextentions/resources/mazeBackground/CoolMazeBackground.png new file mode 100644 index 00000000..4d52cb7a Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/mazeBackground/CoolMazeBackground.png differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Ahem.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Ahem.wav new file mode 100644 index 00000000..9eb535f9 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Ahem.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Applause.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Applause.wav new file mode 100644 index 00000000..3b97f05f Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Applause.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/BrainIsGone.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/BrainIsGone.wav new file mode 100644 index 00000000..44bf6af3 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/BrainIsGone.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/CatMeow.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/CatMeow.wav new file mode 100644 index 00000000..8c03773c Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/CatMeow.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Cheering.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Cheering.wav new file mode 100644 index 00000000..b0daee30 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Cheering.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Crickets.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Crickets.wav new file mode 100644 index 00000000..da2354e4 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Crickets.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/DoctorMccoy.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/DoctorMccoy.wav new file mode 100644 index 00000000..0d12534e Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/DoctorMccoy.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Fanfare.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Fanfare.wav new file mode 100644 index 00000000..020ffbdd Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Fanfare.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/FargoYah.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/FargoYah.wav new file mode 100644 index 00000000..9d9c42d7 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/FargoYah.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Gong.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Gong.wav new file mode 100644 index 00000000..7265cbd5 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Gong.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LLCoolJYaKnow.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LLCoolJYaKnow.wav new file mode 100644 index 00000000..fd391462 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LLCoolJYaKnow.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LosingPower.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LosingPower.wav new file mode 100644 index 00000000..99132ced Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LosingPower.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LoveBeingATurtle.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LoveBeingATurtle.wav new file mode 100755 index 00000000..f0b185ea Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/LoveBeingATurtle.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Malfunction.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Malfunction.wav new file mode 100644 index 00000000..6e87e71c Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Malfunction.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Pizza.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Pizza.wav new file mode 100644 index 00000000..9c4953d8 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Pizza.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/RunAway.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/RunAway.wav new file mode 100644 index 00000000..ab2f25b6 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/RunAway.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/SheerIgnorance.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/SheerIgnorance.wav new file mode 100644 index 00000000..44005b43 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/SheerIgnorance.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/SoBeIt.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/SoBeIt.wav new file mode 100644 index 00000000..014b8c6a Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/SoBeIt.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/StrangePerson.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/StrangePerson.wav new file mode 100644 index 00000000..0a981bb0 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/StrangePerson.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Stubborn.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Stubborn.wav new file mode 100644 index 00000000..84f951e3 Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Stubborn.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Yahoo.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Yahoo.wav new file mode 100644 index 00000000..cd82e4bb Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Yahoo.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Yay.wav b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Yay.wav new file mode 100644 index 00000000..9555196c Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/soundFiles/Yay.wav differ diff --git a/TKPJava/src/main/java/org/teachingextentions/resources/view.rtf b/TKPJava/src/main/java/org/teachingextentions/resources/view.rtf new file mode 100644 index 00000000..7c91f8af Binary files /dev/null and b/TKPJava/src/main/java/org/teachingextentions/resources/view.rtf differ diff --git a/TKPJava/src/main/java/org/teachingextentions/you/need/to/fill/in/the/______.java b/TKPJava/src/main/java/org/teachingextentions/you/need/to/fill/in/the/______.java new file mode 100644 index 00000000..5c307516 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingextentions/you/need/to/fill/in/the/______.java @@ -0,0 +1,5 @@ +package src.main.java.org.teachingextentions.you.need.to.fill.in.the; + +public class ______ +{ +} diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/HolidayCard.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/HolidayCard.java similarity index 97% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/HolidayCard.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/HolidayCard.java index 80ecd5ea..28a4472d 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/HolidayCard.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/HolidayCard.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.inDevelopment; +package src.main.java.org.teachingkidsprogramming.recipes.inDevelopment; public class HolidayCard { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/TicTacToe.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/TicTacToe.java similarity index 87% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/TicTacToe.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/TicTacToe.java index 9a998371..11049b25 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/TicTacToe.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/TicTacToe.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.inDevelopment; +package src.main.java.org.teachingkidsprogramming.recipes.inDevelopment; public class TicTacToe { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/forLoopUpdate.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/forLoopUpdate.java similarity index 78% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/forLoopUpdate.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/forLoopUpdate.java index 4a48795a..f0913373 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/inDevelopment/forLoopUpdate.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/inDevelopment/forLoopUpdate.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.inDevelopment; +package src.main.java.org.teachingkidsprogramming.recipes.inDevelopment; public class forLoopUpdate { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizAdapter.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizAdapter.java similarity index 86% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizAdapter.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizAdapter.java index 3238f3f2..26860ac8 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizAdapter.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizAdapter.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; public class AdLibsQuizAdapter diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizGrader.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizGrader.java similarity index 87% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizGrader.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizGrader.java index 5f0e862c..db70e15e 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizGrader.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/AdLibsQuizGrader.java @@ -1,15 +1,15 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.awt.Font; import java.awt.Graphics2D; import javax.swing.JPanel; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; -import org.teachingextensions.logo.utils.MVCUtils.Parser; -import org.teachingkidsprogramming.recipes.quizzes.graders.AdLibsQuizAdapter.Pieces; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.utils.MVCUtils.Parser; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.AdLibsQuizAdapter.Pieces; public class AdLibsQuizGrader implements Paintable { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuiz.java similarity index 68% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuiz.java index 2376b430..09327617 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuiz.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; public class HiLowQuiz { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuizGrader.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuizGrader.java similarity index 85% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuizGrader.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuizGrader.java index a90dc908..dae7c27e 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuizGrader.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HiLowQuizGrader.java @@ -1,21 +1,21 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.awt.Graphics2D; import javax.swing.JPanel; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.TortoiseUtils; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.EventUtils.MessageBox; -import org.teachingextensions.logo.utils.EventUtils.MessageBox.MessageBoxInstance; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.TortoiseUtils; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.MessageBox; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.MessageBox.MessageBoxInstance; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; public class HiLowQuizGrader implements Paintable { private boolean[] answers; public static int TURTLE_SPEED = 9; - public static MessageBoxInstance MESSAGE_BOX = new MessageBoxInstance(); + public static MessageBoxInstance MESSAGE_BOX = new MessageBoxInstance(); private HiLowQuiz quiz; private void displayScreen() { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizAdapter.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizAdapter.java similarity index 90% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizAdapter.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizAdapter.java index 64ac7982..f82fb0aa 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizAdapter.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizAdapter.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.lang.reflect.Method; diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizGrader.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizGrader.java similarity index 87% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizGrader.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizGrader.java index 5be5b29a..f058b25e 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizGrader.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/HousesQuizGrader.java @@ -1,15 +1,15 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.awt.Graphics2D; import javax.swing.JPanel; -import org.teachingextensions.approvals.lite.util.NumberUtils; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.Turtle; -import org.teachingextensions.logo.utils.TortoiseUtils; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.TortoiseUtils; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.NumberUtils; public class HousesQuizGrader implements Paintable { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/MessageBoxMock.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/MessageBoxMock.java similarity index 50% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/MessageBoxMock.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/MessageBoxMock.java index 8ea7c568..2cb19a7f 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/MessageBoxMock.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/MessageBoxMock.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; -import org.teachingextensions.logo.utils.EventUtils.MessageBox.MessageBoxInstance; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.MessageBox.MessageBoxInstance; public class MessageBoxMock extends MessageBoxInstance { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonCrazyQuizGrader.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonCrazyQuizGrader.java similarity index 84% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonCrazyQuizGrader.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonCrazyQuizGrader.java index 4fe49b89..0a20e88a 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonCrazyQuizGrader.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonCrazyQuizGrader.java @@ -1,18 +1,18 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.awt.Color; import java.awt.Graphics2D; import javax.swing.JPanel; -import org.teachingextensions.approvals.lite.util.NumberUtils; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.Turtle; -import org.teachingextensions.logo.utils.TortoiseUtils; -import org.teachingextensions.logo.utils.ColorUtils.ColorWheel; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.ColorUtils.Wheel; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.TortoiseUtils; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.ColorWheel; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.Wheel; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.NumberUtils; public class PentagonCrazyQuizGrader implements Paintable { @@ -22,7 +22,7 @@ public class PentagonCrazyQuizGrader implements Paintable private boolean mockStitch = false; private int count = 0; private String stitchingAngles = "25.601294645002;39.9954094294277;42.2747487414833;47.092558690198;-2.788677126170;8.082119014691;1.677864557623;3.746613109730;-25.826803494618;-67.5809589960839;-44.8780585363725;6.8440829952860;-18.9074111387679;-18.3392015893888;-22.0596908668138;-54.1385093815182;-73.2696242839109;-29.575128866738;-31.059191548109;-10.233377619284;3.083410700787;2.177224859757;12.620249199431;10.091222647431;-2.514163030606;-0.619322986136;19.377048562492;3.967384838321;20.365744867635;8.924468620782;5.247906731382;38.2861906270044;53.6722312927899;33.3231228793197;21.8612545917246;18.7599063446845;-1.9345991831263;11.1144118699626;-4.3183191159596;-0.4578370883930;20.6609500932546;-3.8233412487789;-32.1839398800777;17.4765102360018;28.6786604159701;-1.1959813284483;-5.7224879538386;-10.3016495267062;-63.9467251702219;-63.8779449224642;-30.3504986035853;-19.8687944708732;-21.978159282607;-14.363027757691;-16.463967303497;-23.821840937835;0.926592976539;-39.940321197861;-31.972205891899;-19.866181322959;0.031467825853;-33.734964949504;-9.726424741340;8.374963042147;5.816868521146;-8.073061677634;-3.548073295589;117.947684481056;2.034836317127;11.764854710885;19.126654192579;10.631238252889;28.914377802640;19.522477772099;28.4952954806338;32.0543585645222"; - private Wheel wheel; + private Wheel wheel; private void displayScreen() { QuizUtils.prepareScoringScreen(answers, this, TURTLE_SPEED); diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonQuizAdapter.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonQuizAdapter.java similarity index 81% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonQuizAdapter.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonQuizAdapter.java index 6c48a7ab..4ba761b0 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonQuizAdapter.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/PentagonQuizAdapter.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; public class PentagonQuizAdapter { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/QuizUtils.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/QuizUtils.java similarity index 78% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/QuizUtils.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/QuizUtils.java index 0dfe8ac5..9270f584 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/QuizUtils.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/QuizUtils.java @@ -1,10 +1,10 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.Turtle; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; -import org.teachingextensions.logo.utils.TortoiseUtils; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.TortoiseUtils; import java.awt.*; diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizAdapter.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizAdapter.java similarity index 86% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizAdapter.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizAdapter.java index 9aa3063d..79bd5f3e 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizAdapter.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizAdapter.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; public class SimpleBubbleQuizAdapter { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizGrader.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizGrader.java similarity index 83% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizGrader.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizGrader.java index 1d24a265..aa69b55e 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizGrader.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleBubbleQuizGrader.java @@ -1,9 +1,9 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Text; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Text; import javax.swing.*; import java.awt.*; diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleSquareQuizGrader.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleSquareQuizGrader.java similarity index 78% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleSquareQuizGrader.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleSquareQuizGrader.java index a1f2cee8..53098b66 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleSquareQuizGrader.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SimpleSquareQuizGrader.java @@ -1,14 +1,14 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.awt.Color; import java.awt.Graphics2D; import javax.swing.JPanel; -import org.teachingextensions.approvals.lite.util.NumberUtils; -import org.teachingextensions.logo.Turtle; -import org.teachingextensions.logo.utils.TortoiseUtils; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.NumberUtils; +import src.main.java.org.teachingextentions.logo.TortoiseUtils; +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; public class SimpleSquareQuizGrader implements Paintable { @@ -48,7 +48,8 @@ private boolean grade1Move() TortoiseUtils.setTurtle(QuizUtils.createTestTurtle()); TortoiseUtils.setOrientation(0, 0, 90); quiz.question1(); - return NumberUtils.equals(TortoiseUtils.getTurtle().getX(), 110, 0.005); + return NumberUtils + .equals(TortoiseUtils.getTurtle().getX(), 110, 0.005); } private boolean grade3Color() { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderQuiz.java similarity index 84% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderQuiz.java index d07c82ae..5e87855d 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderQuiz.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; public class SpiderQuiz { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderWebQuizGrader.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderWebQuizGrader.java similarity index 86% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderWebQuizGrader.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderWebQuizGrader.java index 7a5a30fa..8471b8d5 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderWebQuizGrader.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SpiderWebQuizGrader.java @@ -1,14 +1,14 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.awt.Graphics2D; import javax.swing.JPanel; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.TortoiseUtils; -import org.teachingextensions.logo.utils.ColorUtils.ColorWheel; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.TortoiseUtils; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.ColorWheel; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; public class SpiderWebQuizGrader implements Paintable { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SquareQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SquareQuiz.java similarity index 60% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SquareQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SquareQuiz.java index 051fa9cc..c0ac1547 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/SquareQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/SquareQuiz.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; public interface SquareQuiz { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizAdapter.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizAdapter.java similarity index 91% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizAdapter.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizAdapter.java index 26475e5a..65277d72 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizAdapter.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizAdapter.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.lang.reflect.Method; import java.util.HashMap; diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizGrader.java b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizGrader.java similarity index 90% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizGrader.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizGrader.java index e014c342..23ec57e1 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizGrader.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/recipes/quizzes/graders/TreeQuizGrader.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.recipes.quizzes.graders; +package src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders; import java.awt.BasicStroke; import java.awt.Graphics2D; @@ -6,10 +6,10 @@ import javax.swing.JPanel; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.TortoiseUtils; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Paintable; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.TortoiseUtils; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Paintable; public class TreeQuizGrader implements Paintable { @@ -68,7 +68,7 @@ public void drawRewardShape() TortoiseUtils.setOrientation(xTop - 15, yTop + 15, 90); quiz.length = 15; quiz.question1(); - Tortoise.setPenColor(PenColors.Greens.Lime); + Tortoise.setPenColor(PenColors.Greens.Lime); Tortoise.setPenWidth(2); int[] turns = {0, 90, diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section00demos/QuickShape.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section00demos/QuickShape.java similarity index 85% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section00demos/QuickShape.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section00demos/QuickShape.java index b77c4115..27b3c58d 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section00demos/QuickShape.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section00demos/QuickShape.java @@ -1,8 +1,8 @@ -package org.teachingkidsprogramming.section00demos; +package src.main.java.org.teachingkidsprogramming.section00demos; import java.util.Random; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; @SuppressWarnings("unused") public class QuickShape diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section00demos/QuickTortoise.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section00demos/QuickTortoise.java similarity index 57% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section00demos/QuickTortoise.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section00demos/QuickTortoise.java index f1cc7a98..24056714 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section00demos/QuickTortoise.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section00demos/QuickTortoise.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section00demos; +package src.main.java.org.teachingkidsprogramming.section00demos; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; public class QuickTortoise { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/DeepDive01ForLoops.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/DeepDive01ForLoops.java similarity index 95% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/DeepDive01ForLoops.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/DeepDive01ForLoops.java index 6722bfa7..13282922 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/DeepDive01ForLoops.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/DeepDive01ForLoops.java @@ -1,11 +1,11 @@ -package org.teachingkidsprogramming.section01forloops; +package src.main.java.org.teachingkidsprogramming.section01forloops; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.Turtle; -import org.teachingextensions.logo.utils.TortoiseUtils; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.TortoiseUtils; public class DeepDive01ForLoops { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/DoubleLoop.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/DoubleLoop.java similarity index 85% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/DoubleLoop.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/DoubleLoop.java index df4701bb..3b843e1f 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/DoubleLoop.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/DoubleLoop.java @@ -1,8 +1,8 @@ -package org.teachingkidsprogramming.section01forloops; +package src.main.java.org.teachingkidsprogramming.section01forloops; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.ColorWheel; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.ColorWheel; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; public class DoubleLoop { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/SimpleSquare.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/SimpleSquare.java similarity index 80% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/SimpleSquare.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/SimpleSquare.java index 91e458d9..16888544 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/SimpleSquare.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/SimpleSquare.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section01forloops; +package src.main.java.org.teachingkidsprogramming.section01forloops; public class SimpleSquare { @@ -13,6 +13,6 @@ public static void main(String[] args) throws Exception // End Repeat --#5.2 // // (Optional): Sign your work using the Virtual Proctor - // See your work at http://virtualproctor.tkpjava.org + // See your work at `http://proctor.tkpjava.org` } } diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/SimpleSquareQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/SimpleSquareQuiz.java similarity index 62% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/SimpleSquareQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/SimpleSquareQuiz.java index 53f8972d..90806b17 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/SimpleSquareQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/SimpleSquareQuiz.java @@ -1,7 +1,7 @@ -package org.teachingkidsprogramming.section01forloops; +package src.main.java.org.teachingkidsprogramming.section01forloops; -import org.teachingkidsprogramming.recipes.quizzes.graders.SimpleSquareQuizGrader; -import org.teachingkidsprogramming.recipes.quizzes.graders.SquareQuiz; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.SimpleSquareQuizGrader; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.SquareQuiz; public class SimpleSquareQuiz implements SquareQuiz { @@ -21,7 +21,7 @@ public void question4() { // Change the width of the line the tortoise draws to 5 pixels } - public static void main(String[] args) + public static void main(final String[] args) { new SimpleSquareQuizGrader().grade(new SimpleSquareQuiz()); } diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/Spiral.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/Spiral.java similarity index 84% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/Spiral.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/Spiral.java index 482d9ae2..aec810a1 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section01forloops/Spiral.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/Spiral.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section01forloops; +package src.main.java.org.teachingkidsprogramming.section01forloops; -import org.teachingextensions.logo.utils.EventUtils.MessageBox; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.MessageBox; public class Spiral { diff --git a/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/org/teachingkidsprogramming/section01forloops/org/teachingkidsprogramming/section01forloops/MakeALogo.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/org/teachingkidsprogramming/section01forloops/org/teachingkidsprogramming/section01forloops/MakeALogo.java new file mode 100644 index 00000000..def57e57 --- /dev/null +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section01forloops/org/teachingkidsprogramming/section01forloops/org/teachingkidsprogramming/section01forloops/MakeALogo.java @@ -0,0 +1,19 @@ +package src.main.java.org.teachingkidsprogramming.section01forloops.org.teachingkidsprogramming.section01forloops.org.teachingkidsprogramming.section01forloops; + +public class MakeALogo +{ + public static int YValue = 300; + public static int XValue = 100; + public static void main(String[] args) + { + // Show the Tortoise --#1 + // Make the Tortoise draw a line as fast as possible --#2 + // Setup the Color Wheel --#3 HINT: Use the TKPLogo object + // Draw a TKP 'T' --#4 + // Draw a left bracket --#8 + // Draw a TKP 'K' --#5 + // Draw a right bracket --#9 + // Draw an outer TKP 'P' --#6 + // Draw an inner TKP 'P' --#7 + } +} diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/DeepDive02Variables.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/DeepDive02Variables.java similarity index 98% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/DeepDive02Variables.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/DeepDive02Variables.java index e7fd139d..16f6bd5d 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/DeepDive02Variables.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/DeepDive02Variables.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section02methods; +package src.main.java.org.teachingkidsprogramming.section02methods; import org.junit.Assert; import org.junit.Test; diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/FourSquare.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/FourSquare.java similarity index 91% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/FourSquare.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/FourSquare.java index 65d1eb3a..27007ff6 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/FourSquare.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/FourSquare.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section02methods; +package src.main.java.org.teachingkidsprogramming.section02methods; public class FourSquare { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/Houses.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/Houses.java similarity index 89% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/Houses.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/Houses.java index 9baabf68..54dde28e 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/Houses.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/Houses.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section02methods; +package src.main.java.org.teachingkidsprogramming.section02methods; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; public class Houses { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/HousesQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/HousesQuiz.java similarity index 84% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/HousesQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/HousesQuiz.java index c7706152..707a2042 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/HousesQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/HousesQuiz.java @@ -1,7 +1,7 @@ -package org.teachingkidsprogramming.section02methods; +package src.main.java.org.teachingkidsprogramming.section02methods; -import org.teachingkidsprogramming.recipes.quizzes.graders.HousesQuizAdapter; -import org.teachingkidsprogramming.recipes.quizzes.graders.HousesQuizGrader; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.HousesQuizAdapter; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.HousesQuizGrader; public class HousesQuiz extends HousesQuizAdapter { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/PyramidsOfGiza.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/PyramidsOfGiza.java similarity index 84% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/PyramidsOfGiza.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/PyramidsOfGiza.java index 04a44c48..733dbc81 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/PyramidsOfGiza.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/PyramidsOfGiza.java @@ -1,7 +1,7 @@ -package org.teachingkidsprogramming.section02methods; +package src.main.java.org.teachingkidsprogramming.section02methods; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; public class PyramidsOfGiza { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/TriangleShell.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/TriangleShell.java similarity index 93% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/TriangleShell.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/TriangleShell.java index f910d751..e2a366d1 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section02methods/TriangleShell.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section02methods/TriangleShell.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section02methods; +package src.main.java.org.teachingkidsprogramming.section02methods; @SuppressWarnings("unused") public class TriangleShell diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/ChooseYourOwnAdventure.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/ChooseYourOwnAdventure.java similarity index 84% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/ChooseYourOwnAdventure.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/ChooseYourOwnAdventure.java index 80471ff2..723b8275 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/ChooseYourOwnAdventure.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/ChooseYourOwnAdventure.java @@ -1,15 +1,15 @@ -package org.teachingkidsprogramming.section03ifs; +package src.main.java.org.teachingkidsprogramming.section03ifs; import java.awt.Color; -import org.teachingextensions.approvals.lite.util.ThreadUtils; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.EventUtils.MessageBox; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.ThreadUtils; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.MessageBox; public class ChooseYourOwnAdventure { - public static void main(String[] args) + public static void main(final String[] args) { startStory(); } @@ -17,7 +17,7 @@ private static void startStory() { tellMoreStory("One morning the Tortoise woke up in a dream."); animateStartStory(); - String action = askAQuestion("Do you want to 'wake up' or 'explore' the dream?"); + final String action = askAQuestion("Do you want to 'wake up' or 'explore' the dream?"); if ("wake up".equalsIgnoreCase(action)) { // wakeUp (recipe below) --#2.1 @@ -78,13 +78,13 @@ private static void animateStartStory() ThreadUtils.sleep(100); } } - private static void tellMoreStory(String message) + private static void tellMoreStory(final String message) { MessageBox.showMessage(message); } - private static String askAQuestion(String question) + private static String askAQuestion(final String question) { - String answer = MessageBox.askForTextInput(question); + final String answer = MessageBox.askForTextInput(question); return answer; } } diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/ConcentricLoop.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/ConcentricLoop.java similarity index 86% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/ConcentricLoop.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/ConcentricLoop.java index 9bcd67a2..709d3de9 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/ConcentricLoop.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/ConcentricLoop.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section03ifs; +package src.main.java.org.teachingkidsprogramming.section03ifs; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; public class ConcentricLoop { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/DeepDive03Ifs.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/DeepDive03Ifs.java similarity index 98% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/DeepDive03Ifs.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/DeepDive03Ifs.java index 521135d6..508213f7 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/DeepDive03Ifs.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/DeepDive03Ifs.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section03ifs; +package src.main.java.org.teachingkidsprogramming.section03ifs; import org.junit.Assert; import org.junit.Test; diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/HiLow.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/HiLow.java similarity index 92% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/HiLow.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/HiLow.java index ce7a6b71..e7b5fd37 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/HiLow.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/HiLow.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section03ifs; +package src.main.java.org.teachingkidsprogramming.section03ifs; public class HiLow { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/HiLowQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/HiLowQuiz.java similarity index 73% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/HiLowQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/HiLowQuiz.java index 534737c2..f8b8d575 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section03ifs/HiLowQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section03ifs/HiLowQuiz.java @@ -1,8 +1,8 @@ -package org.teachingkidsprogramming.section03ifs; +package src.main.java.org.teachingkidsprogramming.section03ifs; -import org.teachingkidsprogramming.recipes.quizzes.graders.HiLowQuizGrader; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.HiLowQuizGrader; -public class HiLowQuiz extends org.teachingkidsprogramming.recipes.quizzes.graders.HiLowQuiz +public class HiLowQuiz extends src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.HiLowQuiz { @Override public void question1() diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/BackgroundPhoto.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/BackgroundPhoto.java similarity index 88% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/BackgroundPhoto.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/BackgroundPhoto.java index 5105801b..f7af6131 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/BackgroundPhoto.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/BackgroundPhoto.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section04mastery; +package src.main.java.org.teachingkidsprogramming.section04mastery; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; public class BackgroundPhoto { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/DeepDive04Mastery.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/DeepDive04Mastery.java similarity index 96% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/DeepDive04Mastery.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/DeepDive04Mastery.java index 04d36392..5f9b7ce1 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/DeepDive04Mastery.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/DeepDive04Mastery.java @@ -1,9 +1,9 @@ -package org.teachingkidsprogramming.section04mastery; +package src.main.java.org.teachingkidsprogramming.section04mastery; import org.junit.Assert; import org.junit.Test; -import you.need.to.fill.in.the.______; +import src.main.java.org.teachingextentions.you.need.to.fill.in.the.______; @SuppressWarnings("unused") public class DeepDive04Mastery diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/DigiFlower.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/DigiFlower.java similarity index 87% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/DigiFlower.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/DigiFlower.java index f3fe9fb2..570d8c0f 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/DigiFlower.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/DigiFlower.java @@ -1,9 +1,9 @@ -package org.teachingkidsprogramming.section04mastery; +package src.main.java.org.teachingkidsprogramming.section04mastery; import java.awt.Color; -import org.teachingextensions.logo.utils.ColorUtils.ColorWheel; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.ColorWheel; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; public class DigiFlower { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/KnottedRing.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/KnottedRing.java similarity index 83% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/KnottedRing.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/KnottedRing.java index 59879d6a..743053ca 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/KnottedRing.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/KnottedRing.java @@ -1,8 +1,8 @@ -package org.teachingkidsprogramming.section04mastery; +package src.main.java.org.teachingkidsprogramming.section04mastery; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.ColorWheel; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.ColorWheel; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; public class KnottedRing { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/PentagonCrazy.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/PentagonCrazy.java similarity index 92% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/PentagonCrazy.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/PentagonCrazy.java index 09421e74..de4db195 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/PentagonCrazy.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/PentagonCrazy.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section04mastery; +package src.main.java.org.teachingkidsprogramming.section04mastery; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; public class PentagonCrazy { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/PentagonCrazyQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/PentagonCrazyQuiz.java similarity index 66% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/PentagonCrazyQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/PentagonCrazyQuiz.java index 02f33971..a51a7d3b 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section04mastery/PentagonCrazyQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section04mastery/PentagonCrazyQuiz.java @@ -1,9 +1,10 @@ -package org.teachingkidsprogramming.section04mastery; +package src.main.java.org.teachingkidsprogramming.section04mastery; -import org.teachingkidsprogramming.recipes.quizzes.graders.PentagonCrazyQuizGrader; -import org.teachingkidsprogramming.recipes.quizzes.graders.PentagonQuizAdapter; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.PentagonCrazyQuizGrader; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.PentagonQuizAdapter; -public class PentagonCrazyQuiz extends PentagonQuizAdapter +public class PentagonCrazyQuiz extends + PentagonQuizAdapter { public void question1() { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/DeepDive05Recursion.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/DeepDive05Recursion.java similarity index 94% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/DeepDive05Recursion.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/DeepDive05Recursion.java index 85f8a8a1..b9dc1f41 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/DeepDive05Recursion.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/DeepDive05Recursion.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section05recursion; +package src.main.java.org.teachingkidsprogramming.section05recursion; import java.awt.Color; import java.awt.Cursor; @@ -8,8 +8,8 @@ import org.junit.Assert; import org.junit.Test; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; public class DeepDive05Recursion { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/RecursiveSquare.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/RecursiveSquare.java similarity index 90% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/RecursiveSquare.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/RecursiveSquare.java index 48c055e8..25dcdda4 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/RecursiveSquare.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/RecursiveSquare.java @@ -1,7 +1,7 @@ -package org.teachingkidsprogramming.section05recursion; +package src.main.java.org.teachingkidsprogramming.section05recursion; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; public class RecursiveSquare { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/SpiderWeb.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/SpiderWeb.java similarity index 92% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/SpiderWeb.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/SpiderWeb.java index 3db366e2..4f2de1fb 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/SpiderWeb.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/SpiderWeb.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section05recursion; +package src.main.java.org.teachingkidsprogramming.section05recursion; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; public class SpiderWeb { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/TreeQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/TreeQuiz.java similarity index 80% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/TreeQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/TreeQuiz.java index 8ba58494..67301663 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/TreeQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/TreeQuiz.java @@ -1,7 +1,7 @@ -package org.teachingkidsprogramming.section05recursion; +package src.main.java.org.teachingkidsprogramming.section05recursion; -import org.teachingkidsprogramming.recipes.quizzes.graders.TreeQuizAdapter; -import org.teachingkidsprogramming.recipes.quizzes.graders.TreeQuizGrader; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.TreeQuizAdapter; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.TreeQuizGrader; public class TreeQuiz extends TreeQuizAdapter { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/TurtleTree.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/TurtleTree.java similarity index 94% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/TurtleTree.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/TurtleTree.java index 77b31274..dd74b0a7 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section05recursion/TurtleTree.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section05recursion/TurtleTree.java @@ -1,9 +1,9 @@ -package org.teachingkidsprogramming.section05recursion; +package src.main.java.org.teachingkidsprogramming.section05recursion; import java.awt.Color; import java.util.HashMap; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; public class TurtleTree { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibs.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibs.java similarity index 89% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibs.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibs.java index 65f70c38..80e8b022 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibs.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibs.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section06modelviewcontroller; +package src.main.java.org.teachingkidsprogramming.section06modelviewcontroller; public class AdLibs { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsQuiz.java similarity index 72% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsQuiz.java index 3bc77a19..29c7d0ea 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsQuiz.java @@ -1,7 +1,7 @@ -package org.teachingkidsprogramming.section06modelviewcontroller; +package src.main.java.org.teachingkidsprogramming.section06modelviewcontroller; -import org.teachingkidsprogramming.recipes.quizzes.graders.AdLibsQuizAdapter; -import org.teachingkidsprogramming.recipes.quizzes.graders.AdLibsQuizGrader; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.AdLibsQuizAdapter; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.AdLibsQuizGrader; public class AdLibsQuiz extends AdLibsQuizAdapter { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsRtf.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsRtf.java similarity index 88% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsRtf.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsRtf.java index cf0abe93..1bde6204 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsRtf.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/AdLibsRtf.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section06modelviewcontroller; +package src.main.java.org.teachingkidsprogramming.section06modelviewcontroller; public class AdLibsRtf diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/DeepDive06ModelViewController.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/DeepDive06ModelViewController.java similarity index 97% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/DeepDive06ModelViewController.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/DeepDive06ModelViewController.java index 15046a95..80d9b9d4 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/DeepDive06ModelViewController.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/DeepDive06ModelViewController.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section06modelviewcontroller; +package src.main.java.org.teachingkidsprogramming.section06modelviewcontroller; import java.awt.Color; import java.awt.Cursor; @@ -6,7 +6,7 @@ import org.junit.Assert; import org.junit.Test; -import org.teachingextensions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Tortoise; @SuppressWarnings("unused") public class DeepDive06ModelViewController diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/OneFishTwoFish.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/OneFishTwoFish.java similarity index 94% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/OneFishTwoFish.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/OneFishTwoFish.java index 74f0385d..1b720be2 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section06modelviewcontroller/OneFishTwoFish.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section06modelviewcontroller/OneFishTwoFish.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section06modelviewcontroller; +package src.main.java.org.teachingkidsprogramming.section06modelviewcontroller; //*************This Lesson is In Development*****************************// @SuppressWarnings("unused") diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/CloneTurtles.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/CloneTurtles.java similarity index 96% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/CloneTurtles.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/CloneTurtles.java index 7c15f658..a176c7c0 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/CloneTurtles.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/CloneTurtles.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section07objects; +package src.main.java.org.teachingkidsprogramming.section07objects; public class CloneTurtles { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/DeepDive07Objects.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/DeepDive07Objects.java similarity index 92% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/DeepDive07Objects.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/DeepDive07Objects.java index c7030fd6..ffac59c7 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/DeepDive07Objects.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/DeepDive07Objects.java @@ -1,14 +1,14 @@ -package org.teachingkidsprogramming.section07objects; +package src.main.java.org.teachingkidsprogramming.section07objects; import java.awt.Cursor; import org.junit.Assert; import org.junit.Test; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.Turtle; -import org.teachingextensions.logo.Turtle.Animals; -import org.teachingextensions.logo.utils.PizzaUtils.Pizza; -import org.teachingextensions.logo.utils.PizzaUtils.Topping; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.Turtle; +import src.main.java.org.teachingextentions.logo.Turtle.Animals; +import src.main.java.org.teachingextentions.logo.utils.PizzaUtils.Pizza; +import src.main.java.org.teachingextentions.logo.utils.PizzaUtils.Topping; @SuppressWarnings("unused") public class DeepDive07Objects diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/SpiderWebQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/SpiderWebQuiz.java similarity index 80% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/SpiderWebQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/SpiderWebQuiz.java index c5cbf0c1..8d80113b 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/SpiderWebQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/SpiderWebQuiz.java @@ -1,7 +1,7 @@ -package org.teachingkidsprogramming.section07objects; +package src.main.java.org.teachingkidsprogramming.section07objects; -import org.teachingkidsprogramming.recipes.quizzes.graders.SpiderQuiz; -import org.teachingkidsprogramming.recipes.quizzes.graders.SpiderWebQuizGrader; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.SpiderQuiz; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.SpiderWebQuizGrader; public class SpiderWebQuiz extends SpiderQuiz { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/SuperTurtles.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/SuperTurtles.java similarity index 89% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/SuperTurtles.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/SuperTurtles.java index bc5ab2c2..22676620 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/SuperTurtles.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/SuperTurtles.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section07objects; +package src.main.java.org.teachingkidsprogramming.section07objects; -import org.teachingextensions.WindowUtils.MultiTurtleWindow; +import src.main.java.org.teachingextentions.logo.utils.TurtleWindowUtils.MultiTurtleWindow; public class SuperTurtles { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/WhichFish.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/WhichFish.java similarity index 97% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/WhichFish.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/WhichFish.java index 4ec25d05..02004ac7 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section07objects/WhichFish.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section07objects/WhichFish.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section07objects; +package src.main.java.org.teachingkidsprogramming.section07objects; //*************This Lesson is In Development*****************************// public class WhichFish diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/ConnectTheDots.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section08events/ConnectTheDots.java similarity index 84% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/ConnectTheDots.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section08events/ConnectTheDots.java index 67d7f371..e96f4cee 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/ConnectTheDots.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section08events/ConnectTheDots.java @@ -1,10 +1,8 @@ -package org.teachingkidsprogramming.section08events; +package src.main.java.org.teachingkidsprogramming.section08events; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.ColorWheel; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.EventUtils.MouseLeftClickListener; -import org.teachingextensions.logo.utils.EventUtils.MouseRightClickListener; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.*; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.*; public class ConnectTheDots implements MouseRightClickListener, MouseLeftClickListener { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/SimpleBubble.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section08events/SimpleBubble.java similarity index 91% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/SimpleBubble.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section08events/SimpleBubble.java index 5742a749..a839c878 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/SimpleBubble.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section08events/SimpleBubble.java @@ -1,6 +1,6 @@ -package org.teachingkidsprogramming.section08events; +package src.main.java.org.teachingkidsprogramming.section08events; -import org.teachingextensions.logo.utils.EventUtils.MouseLeftClickListener; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.*; public class SimpleBubble implements MouseLeftClickListener { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/SimpleBubbleQuiz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section08events/SimpleBubbleQuiz.java similarity index 74% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/SimpleBubbleQuiz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section08events/SimpleBubbleQuiz.java index 35b8ceda..a464bb24 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section08events/SimpleBubbleQuiz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section08events/SimpleBubbleQuiz.java @@ -1,12 +1,11 @@ -package org.teachingkidsprogramming.section08events; +package src.main.java.org.teachingkidsprogramming.section08events; -import org.teachingextensions.logo.Tortoise; -import org.teachingextensions.logo.utils.ColorUtils.PenColors; -import org.teachingextensions.logo.utils.EventUtils.MouseLeftClickListener; -import org.teachingextensions.logo.utils.EventUtils.MouseRightClickListener; -import org.teachingextensions.logo.utils.LineAndShapeUtils.Text; -import org.teachingkidsprogramming.recipes.quizzes.graders.SimpleBubbleQuizAdapter; -import org.teachingkidsprogramming.recipes.quizzes.graders.SimpleBubbleQuizGrader; +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ColorUtils.PenColors; +import src.main.java.org.teachingextentions.logo.utils.EventUtils.*; +import src.main.java.org.teachingextentions.logo.utils.LineAndShapeUtils.Text; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.SimpleBubbleQuizAdapter; +import src.main.java.org.teachingkidsprogramming.recipes.quizzes.graders.SimpleBubbleQuizGrader; public class SimpleBubbleQuiz extends SimpleBubbleQuizAdapter implements diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzz.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzz.java similarity index 90% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzz.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzz.java index d1e6d9dd..fe6bad45 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzz.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzz.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section09final; +package src.main.java.org.teachingkidsprogramming.section09final; public class FizzBuzz { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzzGoldenMaster.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzzGoldenMaster.java similarity index 86% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzzGoldenMaster.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzzGoldenMaster.java index e8e51d00..24465ce2 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzzGoldenMaster.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzzGoldenMaster.java @@ -1,7 +1,7 @@ -package org.teachingkidsprogramming.section09final; +package src.main.java.org.teachingkidsprogramming.section09final; import org.junit.Test; -import org.teachingextensions.approvals.lite.Approvals; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.Approvals; public class FizzBuzzGoldenMaster { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzzTDD.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzzTDD.java similarity index 91% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzzTDD.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzzTDD.java index 5aff1d66..30327beb 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/FizzBuzzTDD.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/FizzBuzzTDD.java @@ -1,7 +1,6 @@ -package org.teachingkidsprogramming.section09final; +package src.main.java.org.teachingkidsprogramming.section09final; import static org.junit.Assert.assertEquals; - import org.junit.Test; public class FizzBuzzTDD diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/RectangleKata.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/RectangleKata.java similarity index 85% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/RectangleKata.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section09final/RectangleKata.java index 3d1af3a0..62b005d6 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/RectangleKata.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/RectangleKata.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section09final; +package src.main.java.org.teachingkidsprogramming.section09final; public class RectangleKata { diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/SimplePuzzle.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/SimplePuzzle.java similarity index 87% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/SimplePuzzle.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section09final/SimplePuzzle.java index 1327c827..630fe368 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/SimplePuzzle.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/SimplePuzzle.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section09final; +package src.main.java.org.teachingkidsprogramming.section09final; import java.awt.EventQueue; import java.util.Arrays; @@ -7,14 +7,12 @@ import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; -import org.teachingextensions.logo.utils.PuzzleUtils.Puzzle; -import org.teachingextensions.logo.utils.PuzzleUtils.PuzzleAnimation; -import org.teachingextensions.logo.utils.PuzzleUtils.PuzzleBoard; -import org.teachingextensions.logo.utils.PuzzleUtils.PuzzleState; +import src.main.java.org.teachingextentions.logo.utils.PuzzleUtils.*; + public class SimplePuzzle implements Runnable { - public Puzzle puzzle = null; + public Puzzle puzzle = null; public PuzzleState solution = null; public int[] cells = {0, 1, 2, 3, 4, 5, 6, 7, 8}; // diff --git a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/WheelKata.java b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/WheelKata.java similarity index 83% rename from TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/WheelKata.java rename to TKPJava/src/main/java/org/teachingkidsprogramming/section09final/WheelKata.java index 8265f586..9424f0ee 100644 --- a/TeachingKidsProgramming/src/org/teachingkidsprogramming/section09final/WheelKata.java +++ b/TKPJava/src/main/java/org/teachingkidsprogramming/section09final/WheelKata.java @@ -1,4 +1,4 @@ -package org.teachingkidsprogramming.section09final; +package src.main.java.org.teachingkidsprogramming.section09final; public class WheelKata { diff --git a/TKPJava/src/main/java/org/verify-TKP/BrainIsGone.wav b/TKPJava/src/main/java/org/verify-TKP/BrainIsGone.wav new file mode 100644 index 00000000..44bf6af3 Binary files /dev/null and b/TKPJava/src/main/java/org/verify-TKP/BrainIsGone.wav differ diff --git a/TKPJava/src/main/java/org/verify-TKP/HelloTKP.java b/TKPJava/src/main/java/org/verify-TKP/HelloTKP.java new file mode 100644 index 00000000..a3212930 --- /dev/null +++ b/TKPJava/src/main/java/org/verify-TKP/HelloTKP.java @@ -0,0 +1,7 @@ +public class HelloTKP +{ + public static void main( String[] args ) + { + System.out.println( "Hello TKP World!" ); + } +} diff --git a/TKPJava/src/main/java/org/verify-TKP/HelloTKPTortoise.java b/TKPJava/src/main/java/org/verify-TKP/HelloTKPTortoise.java new file mode 100644 index 00000000..cfbd46bd --- /dev/null +++ b/TKPJava/src/main/java/org/verify-TKP/HelloTKPTortoise.java @@ -0,0 +1,33 @@ +import src.main.java.org.teachingextentions.logo.Tortoise; +import src.main.java.org.teachingextentions.logo.utils.ApprovalUtils.general.NumberUtils; + +public class HelloTKPTortoise +{ + public static void main( String[] args ) + { + // TEST 1 - just print something + System.out.println( "Hello TKP Tortoise World!" ); + + // TEST 2 - use a class.method from `teachingextentions` library + Integer i = NumberUtils.getRandomInt(2, 102); + System.out.println("number "+ (i)); + + // TEST 3 - use a Java primitive `JOptionPane` ( becomes `MessageBox`) + // String message = "TKP JOption"; + // JOptionPane.showMessageDialog(null, message); + + // TKPJava `wrapper` for JOptionPane is MessageBox + // MessageBox.showMessage("TKP message"); + + // TEST 4 - use TKPJava Tortoise window + Tortoise.show(); + Tortoise.setSpeed(5); + for (int j = 0; j < 4; j++) { + Tortoise.move(50); + Tortoise.turn(90); + Tortoise.move(50); + } + + + } +} diff --git a/TKP_Launcher.jar b/TKP_Launcher.jar deleted file mode 100644 index ddd75712..00000000 Binary files a/TKP_Launcher.jar and /dev/null differ diff --git a/TeachingKidsProgramming/.project b/TeachingKidsProgramming/.project deleted file mode 100644 index 9d57ee3b..00000000 --- a/TeachingKidsProgramming/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - TeachingKidsProgramming - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/TeachingKidsProgramming/LICENSE.md b/TeachingKidsProgramming/LICENSE.md deleted file mode 100644 index fed464b1..00000000 --- a/TeachingKidsProgramming/LICENSE.md +++ /dev/null @@ -1,217 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright (c) 2011 Teaching Kids Programming (http://www.teachingkidsprogramming.org). All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -## Contributors: -* Lynn Langit -* Samantha Langit -* James Counts -* Genevieve L'Esperance -* Jessica Ellis -* Matt Ballin -* Llewellyn Falco -* Katrina Owen -* June Clarke -* Brick Ellis -* David Coopersmith -* Edgar Melendrez -* Alex Puente -* 8th Grade students from PALM STEM Academy - Moreno Valley, CA - class of 2015-2016 diff --git a/TeachingKidsProgramming/Spiral.jar b/TeachingKidsProgramming/Spiral.jar deleted file mode 100644 index 6170b45f..00000000 Binary files a/TeachingKidsProgramming/Spiral.jar and /dev/null differ diff --git a/TeachingKidsProgramming/build/build.xml b/TeachingKidsProgramming/build/build.xml deleted file mode 100644 index 1e6d749b..00000000 --- a/TeachingKidsProgramming/build/build.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/TeachingKidsProgramming/src/jars/TeachingKidsProgramming.jar b/TeachingKidsProgramming/src/jars/TeachingKidsProgramming.jar deleted file mode 100644 index 8b593772..00000000 Binary files a/TeachingKidsProgramming/src/jars/TeachingKidsProgramming.jar and /dev/null differ diff --git a/devcontainer-local-run.sh b/devcontainer-local-run.sh new file mode 100755 index 00000000..eb720885 --- /dev/null +++ b/devcontainer-local-run.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Syntax: ./devcontainer-local-run.sh [interactive flag] +# +# Usage: +# +# 1. Interactive/debug mode: +# +# ./devcontainer-local-run.sh true +# +# This mode attaches to the container's terminal and runs bash so you can +# inspect the container or run toubleshooting commands. Desktop still runs as +# normal over VNC. +# +# 2. Background mode (default) +# +# ./devcontainer-local-run.sh false +# +# OR +# +# ./devcontainer-local-run.sh +# +# This mode runs the container without attaching to a bash session. Desktop +# runs over VNC. + +INTERACTIVE=${1:-"false"} +DOCKER_RUN_MODE="--detach" +CMD="" +if [ "${INTERACTIVE}" == "true" ]; then + DOCKER_RUN_MODE="--interactive --tty" + CMD="/bin/bash" +fi + +VARIANT=11 + +# Some times vendors patch their images and re-release them under the same tag. +# Pulling the image first ensures the cache is fresh with the most recent security updates. +docker pull mcr.microsoft.com/vscode/devcontainers/java:${VARIANT} + +# Build the devcontainer for TKP +docker build \ + --build-arg VARIANT=${VARIANT} \ + --file ./.devcontainer/DOCKERFILE \ + --tag devcontainer-tkp \ + ./.devcontainer + +# Run the TKP devcontainer +docker run \ + ${DOCKER_RUN_MODE} \ + --rm \ + --publish 6080:6080 \ + --init \ + --security-opt seccomp=unconfined \ + devcontainer-tkp \ + ${CMD} + diff --git a/images/01CreateFolder.png b/images/01CreateFolder.png deleted file mode 100644 index 3de04185..00000000 Binary files a/images/01CreateFolder.png and /dev/null differ diff --git a/images/02MoveZip.png b/images/02MoveZip.png deleted file mode 100644 index 1fc7af98..00000000 Binary files a/images/02MoveZip.png and /dev/null differ diff --git a/images/03ExtractAll.png b/images/03ExtractAll.png deleted file mode 100644 index 89464251..00000000 Binary files a/images/03ExtractAll.png and /dev/null differ diff --git a/images/04TKPLauncher.png b/images/04TKPLauncher.png deleted file mode 100644 index 0c2c64d2..00000000 Binary files a/images/04TKPLauncher.png and /dev/null differ diff --git a/images/05NoJava.png b/images/05NoJava.png deleted file mode 100644 index 0e66dc80..00000000 Binary files a/images/05NoJava.png and /dev/null differ diff --git a/images/06_64bit.png b/images/06_64bit.png deleted file mode 100644 index 4fd63f9e..00000000 Binary files a/images/06_64bit.png and /dev/null differ diff --git a/images/07NoEclipse.png b/images/07NoEclipse.png deleted file mode 100644 index 4d776bfe..00000000 Binary files a/images/07NoEclipse.png and /dev/null differ diff --git a/images/08CreateFolder.png b/images/08CreateFolder.png deleted file mode 100644 index aaa79fa4..00000000 Binary files a/images/08CreateFolder.png and /dev/null differ diff --git a/images/09MoveZip.png b/images/09MoveZip.png deleted file mode 100644 index 4b7f2b04..00000000 Binary files a/images/09MoveZip.png and /dev/null differ diff --git a/images/10Open.png b/images/10Open.png deleted file mode 100644 index 57a0ec6f..00000000 Binary files a/images/10Open.png and /dev/null differ diff --git a/images/11TKPLauncher.png b/images/11TKPLauncher.png deleted file mode 100644 index ee406673..00000000 Binary files a/images/11TKPLauncher.png and /dev/null differ diff --git a/images/12Untrusted.png b/images/12Untrusted.png deleted file mode 100644 index 8eb6f96f..00000000 Binary files a/images/12Untrusted.png and /dev/null differ diff --git a/images/13Settings.png b/images/13Settings.png deleted file mode 100644 index 31408a8b..00000000 Binary files a/images/13Settings.png and /dev/null differ diff --git a/images/14OpenAnyway.png b/images/14OpenAnyway.png deleted file mode 100644 index a6182813..00000000 Binary files a/images/14OpenAnyway.png and /dev/null differ diff --git a/images/15NoJava.png b/images/15NoJava.png deleted file mode 100644 index a6c18bd7..00000000 Binary files a/images/15NoJava.png and /dev/null differ diff --git a/images/16JDK.png b/images/16JDK.png deleted file mode 100644 index 7d000a2f..00000000 Binary files a/images/16JDK.png and /dev/null differ diff --git a/images/17JDK2.png b/images/17JDK2.png deleted file mode 100644 index 3e8ec092..00000000 Binary files a/images/17JDK2.png and /dev/null differ diff --git a/images/18NoEclipse.png b/images/18NoEclipse.png deleted file mode 100644 index 7e004bf5..00000000 Binary files a/images/18NoEclipse.png and /dev/null differ diff --git a/images/19Eclipse.png b/images/19Eclipse.png deleted file mode 100644 index d23836f0..00000000 Binary files a/images/19Eclipse.png and /dev/null differ diff --git a/images/20Success.png b/images/20Success.png deleted file mode 100644 index e62f5733..00000000 Binary files a/images/20Success.png and /dev/null differ diff --git a/images/21Luna.png b/images/21Luna.png deleted file mode 100644 index 9697faa7..00000000 Binary files a/images/21Luna.png and /dev/null differ diff --git a/images/download zip.png b/images/download zip.png deleted file mode 100644 index 6e4a3ffe..00000000 Binary files a/images/download zip.png and /dev/null differ diff --git a/images/download_zip.png b/images/download_zip.png deleted file mode 100644 index 6e4a3ffe..00000000 Binary files a/images/download_zip.png and /dev/null differ diff --git a/install.sh b/install.sh deleted file mode 100644 index a7db2843..00000000 --- a/install.sh +++ /dev/null @@ -1,17 +0,0 @@ -mkdir ~/TKPSource -cd ~/TKPSource -wget https://github.com/clockwisemusic/TeachingKidsProgramming.Java/archive/master.zip -unzip master.zip -rm master.zip -mv TeachingKidsProgramming.Java-master TeachingKidsProgramming.Java -cd TeachingKidsProgramming.Java -unzip eclipse_workspace.zip -cp tkp.desktop ~/Desktop -echo Exec=$HOME/eclipse/eclipse -data $HOME/TKPSource/TeachingKidsProgramming.Java >>~/Desktop/tkp.desktop -chmod +x ~/Desktop/tkp.desktop -cd ~/ -wget http://mirror.internode.on.net/pub/eclipse/technology/epp/downloads/release/luna/SR2/eclipse-java-luna-SR2-linux-gtk-x86_64.tar.gz -tar xzf eclipse-java-luna-SR2-linux-gtk-x86_64.tar.gz -rm eclipse-java-luna-SR2-linux-gtk-x86_64.tar.gz -~/eclipse/eclipse -data ~/TKPSource/TeachingKidsProgramming.Java -#sudo apt install gnome-color-chooser diff --git a/tkp-lesson-plans/About.md b/tkp-lesson-plans/About.md new file mode 100644 index 00000000..d0d2a679 --- /dev/null +++ b/tkp-lesson-plans/About.md @@ -0,0 +1,14 @@ + +![Teaching Kids Programming Logo](images/tiny-logo.png) + +## Welcome to [Teaching Kids Programming (TKP)](http://www.teachingkidsprogramming.org) Lesson Plans for TKPJava + +This GitHub section contains the lesson plan library for K-12 teachers to use when teaching TKPJava courseware. TKPJava is designed for kids ages 10+ and is most often used with kids at the middle or high school level. + +There is one Lesson Plan for each TKPJava Course. Each lesson plan is designed, written and tested by a group of K-12 teachers and programmers. The Java code for teaching is found on the [TKP repository on Github](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java). This repository includes computer setup instructions (in the README.md file). + +You can use these lesson plans by accessing them via GitHub (online) or by customizing them for your classroom. + +_Happy Teaching!_ + +- Talk to a person: lynn@teachingkidsprogramming.org diff --git a/tkp-lesson-plans/Contents.txt b/tkp-lesson-plans/Contents.txt new file mode 100644 index 00000000..09f23c19 --- /dev/null +++ b/tkp-lesson-plans/Contents.txt @@ -0,0 +1,12 @@ +course100.txt +course01.txt +course02.txt +course03.txt +course04.txt +course05.txt +course06.txt +course07.txt +course08.txt +course09.txt +course09a.txt +course09b.txt diff --git a/tkp-lesson-plans/DatingGame.zip b/tkp-lesson-plans/DatingGame.zip new file mode 100644 index 00000000..8c90b507 Binary files /dev/null and b/tkp-lesson-plans/DatingGame.zip differ diff --git a/tkp-lesson-plans/RESULTS.md b/tkp-lesson-plans/RESULTS.md new file mode 100644 index 00000000..7bad1d85 --- /dev/null +++ b/tkp-lesson-plans/RESULTS.md @@ -0,0 +1,24 @@ +# TKP Impact + +TKP was started in 2007 to give more students access to computer science skills. In addition to being taught to 1000s of students around the world, the impact of TKP is best understood through individual stories. Here are a just a few of those stories.... + +## Gen + +I taught Gen to code via TKP Small Basic and later Java when she was 15. She went on to teach TKP and also contributed to the building of the TKPJava library. Gen gradudated with a degree in CS/Bioinformatics from McGill University. Gen works as a senior software engineer at Doximity - [link](https://www.linkedin.com/in/genevieve-lesperance/). + +## Brick + +Brick's mom, Jessica Ellis, learned TKP Java and then taught it to Brick was he was 15. Brick went on to teach TKPJava and also contributed to the building of their non-profit, TKPLabs, which trains TKP teachers world-wide. Brick graduated with a degree in Math from BYU. Brick works as a software engineer - [link](https://www.linkedin.com/in/brick-e-4bba8a132/). + +## Ian + +My daughter, Samantha Langit, taught Ian TKP Java when we was 17. Ian will graduate with a degree in CS/EE from Standford this spring. Ian is the CTO of a climate action startup -[link](https://www.linkedin.com/in/ian-arko/) + +## Lexina + +I taught Lexie and her sister Linus to code when they were 14 and 16. They went on to start a Digigirl club in their high school and taught TKPJava each week for a year to a group of students. Lexina graduated with a degree in Medicine from University of Zambia. Lexina is a medical doctor -[link](https://www.linkedin.com/in/lexina-zulu-0a796628/) + +## Alex + +8th grade math teacher, David Coopersmith started a STEM program in his middle school using TKP Java. David taught Alex TKPJava when he was in his 8th grade course. Alex was recently awarded a full scholarship to study Computer Science at UC Riverside. + diff --git a/tkp-lesson-plans/SpanishTKP/ 0 Contenido.docx b/tkp-lesson-plans/SpanishTKP/ 0 Contenido.docx new file mode 100755 index 00000000..02dc60af Binary files /dev/null and b/tkp-lesson-plans/SpanishTKP/ 0 Contenido.docx differ diff --git "a/tkp-lesson-plans/SpanishTKP/00 TKP - Informaci\303\263n sobre el Dise\303\261o del Programa.docx" "b/tkp-lesson-plans/SpanishTKP/00 TKP - Informaci\303\263n sobre el Dise\303\261o del Programa.docx" new file mode 100755 index 00000000..74fe3e18 Binary files /dev/null and "b/tkp-lesson-plans/SpanishTKP/00 TKP - Informaci\303\263n sobre el Dise\303\261o del Programa.docx" differ diff --git "a/tkp-lesson-plans/SpanishTKP/01 - Introducci\303\263n a Objetos.docx" "b/tkp-lesson-plans/SpanishTKP/01 - Introducci\303\263n a Objetos.docx" new file mode 100755 index 00000000..62961b63 Binary files /dev/null and "b/tkp-lesson-plans/SpanishTKP/01 - Introducci\303\263n a Objetos.docx" differ diff --git "a/tkp-lesson-plans/SpanishTKP/02 - M\303\251todos y Variables.docx" "b/tkp-lesson-plans/SpanishTKP/02 - M\303\251todos y Variables.docx" new file mode 100755 index 00000000..74f11ce9 Binary files /dev/null and "b/tkp-lesson-plans/SpanishTKP/02 - M\303\251todos y Variables.docx" differ diff --git "a/tkp-lesson-plans/SpanishTKP/03 - L\303\263gica Condicional.docx" "b/tkp-lesson-plans/SpanishTKP/03 - L\303\263gica Condicional.docx" new file mode 100755 index 00000000..6eb33f1a Binary files /dev/null and "b/tkp-lesson-plans/SpanishTKP/03 - L\303\263gica Condicional.docx" differ diff --git a/tkp-lesson-plans/SpanishTKP/04 - Unidad de Dominio (Mastery Unit).docx b/tkp-lesson-plans/SpanishTKP/04 - Unidad de Dominio (Mastery Unit).docx new file mode 100755 index 00000000..7ea1070a Binary files /dev/null and b/tkp-lesson-plans/SpanishTKP/04 - Unidad de Dominio (Mastery Unit).docx differ diff --git "a/tkp-lesson-plans/SpanishTKP/05 - Recursi\303\263n.docx" "b/tkp-lesson-plans/SpanishTKP/05 - Recursi\303\263n.docx" new file mode 100755 index 00000000..a95a1fa8 Binary files /dev/null and "b/tkp-lesson-plans/SpanishTKP/05 - Recursi\303\263n.docx" differ diff --git a/tkp-lesson-plans/SpanishTKP/06 - MVC (Model-View-Controller).docx b/tkp-lesson-plans/SpanishTKP/06 - MVC (Model-View-Controller).docx new file mode 100755 index 00000000..c6997e3b Binary files /dev/null and b/tkp-lesson-plans/SpanishTKP/06 - MVC (Model-View-Controller).docx differ diff --git a/tkp-lesson-plans/SpanishTKP/07 - Objetos e Instancias de Objetos.docx b/tkp-lesson-plans/SpanishTKP/07 - Objetos e Instancias de Objetos.docx new file mode 100755 index 00000000..a21034c9 Binary files /dev/null and b/tkp-lesson-plans/SpanishTKP/07 - Objetos e Instancias de Objetos.docx differ diff --git a/tkp-lesson-plans/SpanishTKP/08 - Eventos y Oyentes de Eventos.docx b/tkp-lesson-plans/SpanishTKP/08 - Eventos y Oyentes de Eventos.docx new file mode 100755 index 00000000..3db2cd0a Binary files /dev/null and b/tkp-lesson-plans/SpanishTKP/08 - Eventos y Oyentes de Eventos.docx differ diff --git a/tkp-lesson-plans/SpanishTKP/09 - Unidad Final.docx b/tkp-lesson-plans/SpanishTKP/09 - Unidad Final.docx new file mode 100755 index 00000000..6008eb1b Binary files /dev/null and b/tkp-lesson-plans/SpanishTKP/09 - Unidad Final.docx differ diff --git "a/tkp-lesson-plans/SpanishTKP/Ense\303\261ando TKPJava- Beta - Codenvy IDE.docx" "b/tkp-lesson-plans/SpanishTKP/Ense\303\261ando TKPJava- Beta - Codenvy IDE.docx" new file mode 100755 index 00000000..c9aa89a0 Binary files /dev/null and "b/tkp-lesson-plans/SpanishTKP/Ense\303\261ando TKPJava- Beta - Codenvy IDE.docx" differ diff --git "a/tkp-lesson-plans/SpanishTKP/M\303\241s all\303\241 de TKP - Fuentes para mayor aprendizaje.docx" "b/tkp-lesson-plans/SpanishTKP/M\303\241s all\303\241 de TKP - Fuentes para mayor aprendizaje.docx" new file mode 100755 index 00000000..2b99ca8c Binary files /dev/null and "b/tkp-lesson-plans/SpanishTKP/M\303\241s all\303\241 de TKP - Fuentes para mayor aprendizaje.docx" differ diff --git a/tkp-lesson-plans/SpanishTKP/TKP-Ecuador.png b/tkp-lesson-plans/SpanishTKP/TKP-Ecuador.png new file mode 100644 index 00000000..6945b86d Binary files /dev/null and b/tkp-lesson-plans/SpanishTKP/TKP-Ecuador.png differ diff --git "a/tkp-lesson-plans/SpanishTKP/Usando la Fuente del Control de GitHub con TKP versi\303\263n Estudiantes.docx" "b/tkp-lesson-plans/SpanishTKP/Usando la Fuente del Control de GitHub con TKP versi\303\263n Estudiantes.docx" new file mode 100755 index 00000000..9f9b275b Binary files /dev/null and "b/tkp-lesson-plans/SpanishTKP/Usando la Fuente del Control de GitHub con TKP versi\303\263n Estudiantes.docx" differ diff --git a/tkp-lesson-plans/TKP-Worksheets.zip b/tkp-lesson-plans/TKP-Worksheets.zip new file mode 100644 index 00000000..277a4c1b Binary files /dev/null and b/tkp-lesson-plans/TKP-Worksheets.zip differ diff --git a/tkp-lesson-plans/Videos-TKPJava.docx b/tkp-lesson-plans/Videos-TKPJava.docx new file mode 100755 index 00000000..a8d3305d Binary files /dev/null and b/tkp-lesson-plans/Videos-TKPJava.docx differ diff --git a/tkp-lesson-plans/course01.md b/tkp-lesson-plans/course01.md new file mode 100644 index 00000000..bf50a08a --- /dev/null +++ b/tkp-lesson-plans/course01.md @@ -0,0 +1,375 @@ +# Teaching TKPJava Course 01 - Intro to Objects + + +_Objects, Methods and For Loops_ +*** +## Preparing to Teach this Course + +| Every Course | Recipes in This Course | +|-----------------------------------|-------------------------| +| :hourglass: **Install** the [TKPJava courseware](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java#get-started-with-tkp) |**1.** Simple Square - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section01forloops/SimpleSquare.java) | +| :green_book: **Read** this lesson plan page | **2**. Simple Square Variation - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section01forloops/SimpleSquareVariation.java) | +| :computer: **Code** all recipes yourself | **3**. Simple Square Quiz - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section01forloops/SimpleSquareQuiz.java) | +| :bulb: **Review** the [TKPJava Language pptx](http://www.slideshare.net/lynnlangit/tkpjava-teaching-kids-programming-core-java-langauge-concepts) | **4**. Spiral - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section01forloops/Spiral.java) | +|:fax: **Print** the [keyboard shortcut sheet](http://www.slideshare.net/lynnlangit/tkpjava-eclipse-and-codenvy-ide-keyboard-shortcuts) | **5**. Make A Logo - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section01forloops/MakeALogo.java) | +|:fax: **Download and Print** the [recipe worksheet](https://www.dropbox.com/s/9qwbv48p8lmx4nj/TKP-Worksheets.zip?dl=0) | **6**. Double Loop - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section01forloops/DoubleLoop.java) | +|:bar_chart: Keep Learning! | **7**. Deep Dive 01 - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section01forloops/DeepDive01ForLoops.java) | + + +*** +### +Initial TKPJava Courseware Installation +- Install the TKPJava courseware (on GitHub :octocat:) – TeachingKidsProgramming. by following the one page detailed installation instructions for PC or Mac - [here](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java/blob/master/README.md). +- After downloading per the instructions above then double-click the launcher file (**TKP_launcher.jar** - for Windows) to open the customized version of Eclipse to the TKPJava workspace. + - If Eclipse doesn’t open at all, you need to install Java or Eclipse or both. Re-read the instructions (on GitHub) to understand how to manually install Java and/or Eclipse plus the TKPJava courseware on either a PC or a Mac. + - Shown below is an example of how the TKP customized workspace **should** look if the TKP_launcher ran correctly. + +![TKP Eclipse customization](images/TKP_Courseware_SmokeTest.png) +*** + +## Part 1 - **Recipe: Simple Square** + +As this lesson is the beginning of the course, it's quite imporant for the instructor to set the proper tone for the student work. TKPJava is instructor-facilitated via interrogative guidance. + +- To start teaching, pair the students (see 'pair programming' in the previous GitHub course), then have the students read the first line of English (comments) in the SimpleSquare.java code file ("Show the Tortoise" -- #1) out loud. Line numbers are at the end of each line. +- Use the TKP Intentional method to guide students so that THEY can do the translation. Refrain from telling them the answer (Java code) in advance. +- Encourage students to use 'ctrl+space' to get a list of possible items rather than typing out the Java. Note that **Java is case-sensitive**. +- After the students complete translating each line of English into Java, it is very important to MAKE SURE THEY RUN THE CODE BEFORE PROCEEDING. +- A detailed example teaching script for the first line is shown below. + +### LINE NOTES + +To get started, we've provided a complete example (teaching script), to give teachers a blueprint for facilitating TKPJava in the Intentional style. + +_Say: "Read Line #1 out loud". ("Show the Tortoise") + + // Show the Tortoise --#1 + +Ask: "What is the noun in that sentence?" (Tortoise) +Say: "Move your cursor to the end of that line and click, to put the cursor there." +Say: "Press and hold the 'shift' key plus the 'enter' key to add a new blank line below the line you are on now for your Java code.." +Say: "In that new line type Big 'T' then small 'or', then press and hold ctrl+space." + + // Show the Tortoise --#1 + Tor + +Ask: " Do you see the word 'Tortoise' in the drop-down list? +Say: "Click on on that word in the list and press enter to add the Tortoise" + + // Show the Tortoise --#1 + Tortoise + +Say: "In English we separate words with a space, in Java we use a period. Type a dot after Tortoise." + + // Show the Tortoise --#1 + Tortoise. + +Ask: "What is the verb in that sentence?" (show) +Ask: "How do you get your list?" (ctrl+space) +Ask: "Do you see the verb? Notice it starts with small 's' " (show) + + // Show the Tortoise --#1 + Tortoise.s + +Say: "Click on the verb in the list and then press enter to add the verb." (show) + + // Show the Tortoise --#1 + Tortoise.show() + +Say: "How do we end a sentence in English?" (with a period) +Say: "In Java, we use a semi-colon. Type that to end your sentence." + + // Show the Tortoise --#1 + Tortoise.show(); + +Say: "It is important to to make sure you've translated correctly after each line. +To test it out, you have to run your program. To run your program click the (green) play button." +WAIT +Ask: "What did you see?" (A Tortoise!) +Say: "Click the 'X' in the upper right corner to close the window." +Say: "Now we have to clean up our work. To clean up we will delete the English line that we just translated." +Say: "The easiest way to delete that line is to click anywhere in that line, then ctrl+D."_ + +Have the students read Line #2 out loud. +Follow a similar process to the detail listed above for Line #1, i.e. ask questions, etc... + + Tortoise.move(50); + +Remind them to run to verify and then to clean up the English that they have correctly translated. + + Tortoise.turn(90); + +Explain setters and getters - you may wish to show the Getters/Setters slide from the TKPJava-Language.pptx deck to anchor the concept. + +_Say: "Setters change something about an object; getters tell us something about an object."_ +Choose a student to be an object. +Provide an example, i.e. "Set a student’s position to standing / Get a student’s hair color." + Tortoise.setPenColor(PenColors.Blues.blue); + +_NOTE: The reason for the use of 'PenColors' rather than 'Colors' or 'Color' is that there is a 'Color' library in standard Java. The TKP 'PenColors' libary includes custom documentation and examples of using the object. The documentation includes 'color swatches'. There are also several other Java libraries that include a 'Color' or 'Colors' object. Having the students select 'PenColors' guides them to using objects in the TKPJava PenColors library._ + +**For Loop** +_Say: "Read the text at line --#5.1" (// Do the following 4 times) +Ask: "Do you see a line numbered #5.2? What is that for?" (repeat - ends the loop) +Ask: "Which line numbers (of code) need to be repeated?" (line x, y, z...) +Ask: "What is the easiest way to repeat?" (copy and paste four times) +Say: "What is the keyboard shortcut to copy? to paste?" (ctrl+c, ctrl+v)_ + +Have the kids copy and paste the lines 4 times and then run it, then undo back to line + +_Ask: "But what if you had to do it 400 times?" +Say: "Copy/paste over and over, violates the most important rule for programmers – (use your tools). We don’t want to break that rule. So… "_ + +Introduce 'for' loop synax, you may want to use the TKPJava.pptx slide + +To translate, type “for” and then ctrl+space, select the first "for loop template" + - "array.length" needs to be replaced by the number of iterations (4) + - DELETE the second line of the array template + - Move the end bracket down **after** the three lines of code. Use alt+down, to move the end bracket to bottom of loop code. + + for (int i = 0; i < array.length; i++) { //loop body here } + +_Tip: Make sure they run it to verify. Check – easy to mess this one up!_ + +After eliciting the command, ask: how do we know what is “as fast as possible”? +Have the students click on the 'setSpeed( )' method and direct them to look at the example in the Javadoc window to see how to assign the appropriate value for speed (10). + + Tortoise.setSpeed(10); + +_CONGRATULATIONS! You just made your first program!_ + +:large_blue_diamond: _Tip: You can use http://virtualproctor.tkpjava.org from any computer to show student windows on screen when they close their window. We like to run the TKP Virtual Proctor from the instructor's computer and project the screen so that the kid's can 'see' what they are all coding (example shown below)._ -- IMPORTANT: URL updated to `http://proctor.tkpjava.org` + +![screen-shot-2015-07-13-at-82649-pm.png](images/screen-shot-2015-07-13-at-82649-pm.png) + +Here are some optional lines to personalize the view in the Virtual Proctor + +```java + + // NOTE: see your work at `http://proctor.tkpjava.org` / + // Set your classroom name for the Virtual Proctor --#6.1 (optional) + VirtualProctor.setClassName("TKPworld"); + // Set your student name for the Virtual Proctor --#6.2 (optional) + VirtualProctor.setName("TKPstudent"); +``` + +*** +## Part 2 – Variation: Simple Square +To kick off this section, you may choose to use the TKP Kata Question: + +_"How would you make a triangle here?"_ + +See the TKP Instructional Design (Teaching Variation) section for more information. Here's a graphic that represents the general idea: + +![tkpkataquestionprocess.png](images/tkpkataquestionprocess.png) + + +This is lead as a ‘follow the leader’ style exercise. Open Word or something to scribble in. Draw a feature grid on your whiteboard as shown below. Ask your students – what features are there? Example shown below - (with all later steps completed): +![Screenshot_2014-04-10_at_10.34.50_PM.png](images/Screenshot_2014-04-10_at_10.34.50_PM.png) + +[Here's](https://www.youtube.com/watch?v=kh8w_plilUU) a screencast (video) on how to teach the SimpleSquareVariation. We've made these video for teacher preparation: + +![1b_simplesquarevariation.png](images/1b_simplesquarevariation.png) + + +### Variation Preparation + +Intro to preparation +_Any of these values can be changed. But first, we have to get the code ready to be changed, or it’ll end up a mess!_ +[Add another column – prepare. Must do these before moving on to other things.] + + - Prepare angle + - Hard to change right now + - Go to 90 in code. 90 = quarter of circle. (Spin around.) + - How do we know that 90 is ¼ of 360? Math. (Or memorization.) + - Computers better at this than us. What if we want it to turn 1/7 of a circle? What is 360/7? Uhh… + - Rewrite as 360/4 + - Run, see that it’s the same. [THIS IS IMPORTANT.] + - Put X in “prepare” for angle. + +Prepare sides +Simple refactoring. Go to where it says 4, highlight, right click, refactor, extract local +variable. +Name it “sides” +Run – show that it does exactly the same thing. +[Don’t explain everything here – just show that it runs.] +X it off in the graph. + +Prepare line width +Which line determines this? None. It’s a default. So we’re going to make the default explicit. +FIRST LINE IN for loop, add: Tortoise.setPenWidth(2); +Go back to grid, X it off + +### Other Variation Notes + +[Overall note for variations: try 3-5 numbers, some ridiculously small, some ridiculously big. Don’t use “normal” numbers (20, 100) – use 13, 117, etc.) Don’t go over 1000.] + +New column: “Simple changes” +Add one more column: “Cool changes” +Can change anything, but needed to prepare before we mess around. +Variation: sides +Change sides to 7. +Change sides to 13. +Change sides to 100. +Anyone notice a problem? +Lines don’t meet at a certain point. Why? What is 360/13? Fraction! +Java doesn’t automatically deal with fractions… so change 360 to 360.0 so we’re telling it we’re dealing with fractions. NOTE: You are introducing the concept of a Double vs. an Integer. + +Variation: colors +No refactoring – show green, purple, let them pick a couple of favorites. +Show swatches of color as they arrow down. +Have them find a way to get a random color +Tortoise.setPenColor(Colors.getRandomColor()); +Variation: line width +Start with a few small – 5, 8, 13, 75, 347, bring it back to 7 +Variation: Move length +99, 9, 23. Check it off. (Just quick changes here.) +Cool changes +Every time we run this it does the same thing. Now, let’s make it so user tells us how many sides to include. +Replace sides = 7 with MessageBox + + int sides = MessageBox.askForNumericalInput("How many sides?"); + +Run it – show a few options +Show that sides is in black. So is i. These are variables. +In “setPenWidth”, change 1 to “I”. +Ask: what do they think will happen? +Talk them through what’s happening. How wide is line 1? What about the fifth line? The (next one after the largest?) – there isn’t one. +Do a few more – I * 10, I * 3.5 + + Tortoise.move(i*5); + +Ask about shape: if those were connected, it would be a circle, right? That’s how many degrees? 360. So if you wanted three circles, how many degrees would you need? +(Some student says 1080. “You violated our first rule – let the computer do the math!” So: 360*3.) + +You can have the students set their name(s) on their screen in the Virtual Proctor (if you are using it) - at virtualproctor-tkp-appspot.com by having them add the line below (passing in the names of the kids as a String to the set name method of the Virtual Proctor object. + + VirtualProctor.setName("LynnAndSamantha"); + +Put up virtual proctor on screen and let them play with it, seeing what everyone’s doing. + + +If you are planning to use the Spiral (optional) recipe, then you may want to add a second (nested) for loop in the variation for SimpleSquare, as the Spiral recipe includes this concept, including naming the local variables differently, i.e. 'i' for the first for loop and 'j' for the second for loop. +*** +## Part 3 – Quiz: SimpleSquareQuiz.java + +To locate the .java file, use the keyboard shortcut "cmd-shift-T: SSQ" for (SimpleSquareQuiz) to bring up the Eclipse 'find file' menu + +All TKP quizzes are written to let students celebrate their understanding of the concepts presented. Quizzes are written so that all students who have completed the previous recipes should be able to get 100% correct. + +As a teacher, your role is to facilitate (but **not** to give the correct answers!) by guiding kids toward success. Here are some teaching tips for TKPJava quizzes: + +- Kids work in pairs, teacher faciliates and helps get to kids 'unstuck' by asking questions. +- Tell kids that they simply enter code matching each recipe line, then run and the quiz will grade that line (those lines) to show whether they passed that line (and the entire test). +- Reminds kids to run after **each** question before deleting the English comment line. +- Don’t show – suggest how they can discover for themselves by asking questions. +_E.g. “What do the English say exactly here?”_ +_“That method doesn’t seem to be working for you, is there a different method you could try? .” +“You haven’t gotten question 1 working. Let’s undo and get that working before doing question 2.”_ + +*** + +## Part 4 – Recipe: Spiral + +Open “Spiral.java” - You should point out the 'ColorWheel' object, as this is the first introduction of this object. + +You will introduce the idea of different loop variable names, i.e. 'i' and 'j' in nested for loops. + +Additionally the idea of run-time exceptions is introduced by the deliberate execution path of using colors from the ColorWheel BEFORE colors are added. Having the kids code in the order listed will generate a custom exception in the console window, which is expected and provides an opportunity to introduce the ideas of execution order and null values in a fun way. We added the Java 'try...catch...' exception handling code to surface the expected runtime exception in a MessageBox (shown below) , in case you aren't running Eclipse in debug mode. + +![screen-shot-2015-10-12-at-64447-pm.png](images/screen-shot-2015-10-12-at-64447-pm.png) + +Tip: Running Eclipse in debug allows you to see any generated exception messages in the Console window by default. + +Here is a video recap of the recipe as well -- https://www.youtube.com/watch?v=k1EQTcjcYKM + +If kids finish early, they can try variations. Here's a video showing how to teach Spiral: +“Spiral” + +*** +## Part 5 - Additional Recipe: Make A Logo + +This recipe continues introducing the idea of using an object _other than the Tortoise_when coding TKPJava. The new object in this recipe is the 'TKPLogo'. The TKPLogo object has a number of methods which demonstrate a couple of ideas: + +-- Useful, readable method names - ask the class 'what do think this method does **BEFORE** students run the code + +-- Reinforcement of tool usage - while method names are English-like, they are not exactly the same as English. Kids will code _much faster_ if they following this pattern (and do NOT type out the object and method names letter-by-letter): + -- Type 'TK... , then ctrl+space, then click on 'TKPLogo' and press enter to auto-complete + -- Type a '.' (dot) after the TKPLogo, then ctrl+space + -- Select the method in the list, press enter to auto-complete it + +-- Introduction of the idea of abstraction. In a previous recipe (Spiral), kids coded the instantiation of the ColorWheel, i.e. ColorWheel.addColor(PenColors.Blues.Blue); etc... +In this recipe they do not have to do that. Ask them why not, and also how this same result is achieved. + +Additionally ask about exactly which sets of steps the TKPLogo.draw_tkp_T( ); is performing, i.e. Tortoise.move(x); Tortoise.turn(x), etc... + +You may want to draw the steps out on a whiteboard. You can also open the source code for the [TKPLogo object](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingextensions/logo/utils/TKPLogoUtils/TKPLogo.java) and show the students the amount of abstraction included in this recipe. +*** +## Part 6 - Additional Recipe: Double Loop + +This recipe introduces the idea of a nested loop and also of using different variable names for loop variables, i.e. 'i' and then 'j'. It also introduces the idea of 'hiding' the Turtle. It is designed as a starter to give kids more ideas for variations. Also via the double-loop they can visually understand 'for loops' more deeply. + +Another concept introduced in the recipe is that of translating a recipe which includes mostly English comments, but also some existing Java code. The reason for this type of exercise is to allow for more complex recipes, but to still keep the number of steps the students complete relatively short. In addition the complexity of differentiating between English comments and Java code is supported using this partially completed' lesson. +*** +## Part 7 – Deep Dive: DeepDive01ForLoops.java +**IMPORTANT** Run each test as a first step. It should fail! Read the failure output. + +Tip: To help kids understand 'how to see what you missed' +This one: http://www.youtube.com/watch?v=vJG698U2Mvo +Another one: http://www.youtube.com/watch?v=IGQmdoK_ZfY +Yet another one: [McGurk effect] (http://youtu.be/G-lN8vWm3m0 ) +Say: _'No matter what happens, you’re going to miss a lot of it. So one way to counteract it is to get everyone to volunteer what they see, even if they think it’s very obvious. (Could be as obvious as a gorilla walking across screen, since someone might not have seen it!)'_ + +### SETUP +Chairs at front, circle/oval/whatever – computer at desk to the side. +Give kids post-its. +Each kid writes an observation and the last thing they just did. No talking – they just write. Then collect, and read them to the class. +#### PROCESS +When going through Deep Dive, one student will sit @ computer, another will be standing and will tell them what to type. +After each test, standing student gives observation (/explains why they entered what they did), then they rotate. +If they ask “Does it work if…” then try it and see! +SHOW THEM THE PROCESS +#### numbersDoNotNeedQuotes +Put cursor on method name. Then click on “numbersDoNotNeedQuotes”, run. +Show that it does not work. +Walk them through getting it to work, then have them write observations on it. They read. +#### defaultWidthForTheTortoise +Show failure trace – how do we find the right #? +#### stringsNeedQuotes +Type green +Did not work. Why? Look at the title! +Change to “green”. +We done? Nope! Must run. +Double click on the failure trace when running the failed program – show the window that pops up. +#### theTortoiseTurns15Twice +How is this different from the last one? (Turning twice, but looking at the angle which results from both turns) +#### combiningNumbers +How is this different from the last one? (Adding numbers, looking for total) +#### combiningText +How is this different from the last one? (Adding strings just combines them one after the other.) +#### combiningTextAndNumbers +How is this different from the last one? (Adding a number to a string treats the number as a string.) +Useful techniques – asking how one is different from the last. (E.g., “assigningVariables” vs. “howFastCanTheTortoiseGo” +#### combiningTextInALoop +Ensure the kids get what happened here. Maybe pick one from audience to explain. +#### forLoopsEndAtTheLine +A fairly advanced thing +Double-click in blue thing. Debug dot. +Now, right click on for loop in left part… sends you to debugger. +Use “step over” (yellow arrow top right) to see individual steps. Show the kids how this works. +#### forLoopsCanStartAnywhere +Same as above – have one explain +#### forLoopsCanSkip +Same as above – have one explain +*** + + +## Part 7 – Worksheet: To locate '1_SimpleSquareWorksheet.docx' for printing +Download, unzip and print from - [here](https://www.dropbox.com/s/9qwbv48p8lmx4nj/TKP-Worksheets.zip?dl=0) (contains all worksheets for all courses) +Have kids circle part of code, part of English, draw line between them. +Have them go through it – use teacher version for notes. +*** + + + + diff --git a/tkp-lesson-plans/course02.md b/tkp-lesson-plans/course02.md new file mode 100644 index 00000000..67e2f848 --- /dev/null +++ b/tkp-lesson-plans/course02.md @@ -0,0 +1,165 @@ +# Teaching TKPJava Course 02 - Methods & Variables + +_Using Extract Variable and Extract Method_ + +*** +## Preparing to Teach this Course + +| Every Course | Recipes in This Course | +|-----------------------------------|-------------------------| +| :hourglass: **Install** the [TKPJava courseware](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java#get-started-with-tkp) |**1.** Houses - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section02methods/Houses.java) | +| :green_book: **Read** this lesson plan page | **2**. Houses Variation - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section02methods/HousesVariation.java) | +| :computer: **Code** all recipes yourself | **3**. Houses Quiz - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section02methods/HousesQuiz.java) | +| :bulb: **Review** the [TKPJava Language pptx](http://www.slideshare.net/lynnlangit/tkpjava-teaching-kids-programming-core-java-langauge-concepts) | **4**. FourSquare - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section02methods/FourSquare.java) | +|:fax: **Print** the [keyboard shortcut sheet](http://www.slideshare.net/lynnlangit/tkpjava-eclipse-and-codenvy-ide-keyboard-shortcuts) | **5**. Triangle Shell - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section02methods/TriangleShell.java) | +|:fax: **Print** the main [recipe worksheet](https://www.dropbox.com/s/9qwbv48p8lmx4nj/TKP-Worksheets.zip?dl=0) | **6**. Pyramids of Giza - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section02methods/PyramidsOfGizaEnd.java) | +|:swimmer:|**7**. Deep Dive 02 - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section02methods/DeepDive02Variables.java) | + + +*** +## Part 1 - **Recipe: Houses** + +Recipe Concepts +Create methods and run methods. The programmer way to say run a method is by saying 'call' a method. + +Recipe Guidelines +We are introducing the idea of creating a variable (via refactoring) and also of setting the value of that variable (multiple times) during this recipe. We find it helpful to use the word "current" when talking about variables, i.e. "What is **current** value of the height", etc... + +Another teaching tip is to start by assigning a number to the height BEFORE creating the variable. If you teach this way, remember to have the kids run the recipe each time as you lead them from a number, to a variable name and eventually to a variable which has the current value of the number, i.e. 40. + +Also, lead the students to NOT delete the English comment until AFTER they've completely translated the number into a working variable. This is an important programming concept, we call it 'fake it until you make it'. + +To Refactor: refactor the fake and extract it as a variable, name it “height”. +We have now created line 16: int height=1000 +But it is not translating line 15, so move the code to follow the English its translating and replace the fake number with the information we learn: 40 + + 1.1: Tortoise.move(height); + 1.2: int height = 40; + +Delete English lines 1.1 and 1.2 +This one’s already done now! Run to test, then English can be deleted. +[For 2-8, do them quickly as a class. If they forget to turn numbers negative, just run it and let them be confused. ] + + 2. Tortoise.turn(90); + 3. Tortoise.move(30); + 4. Tortoise.turn(90); + +Ensure they do this the lazy way! (And the following) + + 5. Tortoise.move(height); + +Make sure kids are using “height”, not “40” + + 6. Tortoise.turn(-90); + 7. Tortoise.move(20); + 8. Tortoise.turn(-90); + 9: sub-recipe + +_THIS IS WHERE WE GET TO SOMETHING TOTALLY NEW. +Anyone notice something different about this recipe? – It’s like a recipe within a recipe!_ + +You can show a short (less than 3 minute) video here to show how to do this.[How to extract a method](https://www.youtube.com/watch?v=C6fnqjceVcs "Method Extraction") + +This is a sub-recipe. When you make a cake, there is the recipe for the whole cake and the recipes for the parts: cake, filling, frosting; + +Show them how to extract a method. Highlight from beginning of method to end, INCLUDING comments for line 9 (top and bottom). Choose Refactor Extract Method, then use name of sub-recipe: drawHouse. + +Delete all the line 9s, run and see that it does exactly the same thing. +When we refactor, code should run exactly the same. + +Have kids look at it and try to figure out – what did we just do? Why might this be useful? +Give terminology: method. Why would we do it? If we’re doing the same sort of thing over and over, and want to save typing. Lazy = good. +Make sure they delete the line 9s! + + 10. height = 120; + drawHouse(height); + OR + drawHouse(120); +Before typing – can they see two ways to do this? (hint: one is two lines, one is one) +What might be advantages, disadvantages of each? +Height variable – can be changed more easily later. (E.g., if you want to ask user what height to use.) +120 – less typing. +So a tradeoff, depends on what you want. For now, both do the same! + + 11. Tortoise.setSpeed(10); + +Lots of houses to draw, so let’s get this tortoise moving! +Have them do 12-13 by themselves. They know how. + + 12. drawHouse(90); + 13. drawHouse(20); + 14. Tortoise.setX(200); + +What is the noun? Tortoise. +How are you going to translate this line? “set-x” +“Get” and “set” is easy mistake to make, happens all the time. + + 15. Tortoise.setPenColor(Colors.Grays.LightGray); + +They know how to do this and then Run it! +*** +### Recap Video: Houses + +Focus on creating methods - this is for teacher preparation + +“Houses” +*** +##Part 2 - Houses Variation + +VARIATIONS IN GENERAL +- _“Tell me the attributes of what we’ve made”_ +- Make grid – brainstorm features (necc. ones below) +o Height of buildings +o Width of building +o Number of buildings +o Color of line +o Position of buildings on page +o Number of sides on buildings +- Have the kids pick one to change, ask them where it is in the code. +o Teaching point: if you see it, you can change it. If not, you can expose it, often by refactoring. + +To kick off this section, you may choose to use the TKP Kata Question: + +_"How would you make a slanted roof for your houses?"_ + +See the TKP Instructional Design (Teaching Variation) section for more information. + +Idea to get the kids to draw on a whiteboard to show different ways to make a house's roof, i.e. slanted, flat, pointed, etc... + +![Tortoise For Drawing](images/Tortoise.png) + +Print the Tortoise.png file (above) and cut along the lines and put a marker in the middle of the line. + +![Roof Variations for Houses](images/allRoofs.jpg) + +Write the process out that the Turtle draws to make the new types of roof on the board. +![my roof](images/myRoof.jpg) + +Extract lines that make the roof call the method drawRoof() +Add English to code the method drawSlantedRoof() + +Then change the line color using the Tortoise.setPenColor(Colors.getRandomColor()); +Then change the background using the Tortoise.getBackgroundWindow.setBackground(Colors.Reds.Red); +*** +## Part 3 – Quiz: HousesQuiz.java + +- Warn in advance: this one is complicated, and you will need to be comfortable with some trial and error. +- Remember, ctrl-Z to undo – your best friend! + +*** +## Part 4 – Four Square +Uses two for loops and an extracted method +*** +## Part 5 – Triangle Shell +Uses two for loops and an extracted method and incrementing a local variable (length) +*** +## Part 6 – Pyramids of Giza +Uses multiple levels of method refactoring to remove duplication, i.e. re-factor common code to a method and then re-factor those new methods to yet another new method to remove code duplication. Also introduces the idea of more than one method parameter (in the second level of refactoring), i.e. final methods have TWO variables. +*** +## Part 7 – Deep Dive: DeepDives02Variables.java +More work with variables and variable values, introduces shortcut operators as well (i.e. '++', '--', etc...) +*** +## Part 8 – Worksheet: +Print '2_HousesWorksheet.docx' and have the students complete it. +*** + diff --git a/tkp-lesson-plans/course03.md b/tkp-lesson-plans/course03.md new file mode 100644 index 00000000..4ebc42dc --- /dev/null +++ b/tkp-lesson-plans/course03.md @@ -0,0 +1,147 @@ +# Teaching TKPJava Course 03 - Conditional Logic + + +_More about Methods, and introducing Simple & Complex If-statements_ + +*** +## Preparing to Teach this Course +| Every Course | Recipes in this Course | +|--------------------------------------------------------------|---------------------------------| +| :hourglass: **Install** the [TKPJava courseware](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java#get-started-with-tkp) | **1**. HiLow - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section03ifs/HiLow.java) | +| :green_book: **Read** this lesson plan page | **2**. HiLowVariation - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section03ifs/HiLowVariation.java) | +| :computer: **Code** the recipes yourself | **3**. HiLowQuiz -[answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section03ifs/HiLowQuiz.java) | +| :bulb: **Review** the [TKPJava Language pptx](http://www.slideshare.net/lynnlangit/tkpjava-teaching-kids-programming-core-java-langauge-concepts) | **4**. ConcentricLoop - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section03ifs/ConcentricLoop.java) | +|:fax: **Print** the [worksheet / also keyboard shortcuts cheat sheet](https://www.dropbox.com/s/9qwbv48p8lmx4nj/TKP-Worksheets.zip?dl=0) | **5**. ChooseYourOwnAdventure - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section03ifs/ChooseYourOwnAdventure.java) | +|:bulb: **Review** the recipe / lesson answer files | **6**. DeepDive03 - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section03ifs/DeepDive03Ifs.java) | + +*** +## Part 1 - **Recipe: HiLow Game** +This course introduces conditional logic with increasingly complex Java if..., if...else If...., etc...control flow structures. We also introduce the idea of 'exit' points, or end of program code. + +Additionally, in this course, we use a random number generator that we wrote for TKPJava. +The line referring to using a random number can be translated in two ways. We make use of a utility library (NumberUtils) that we wrote to simplify the creation of a random number (as shown below). + + // Choose a random number between 1 and 100 --#4.1 (fake!) & --#13 + int answer = NumberUtils.getRandomInt(1, 100); + +Alternatively you could use the "classic" Java pattern as shown below: + + Random randomGenerator = new Random(); + int randomInt = randomGenerator.nextInt(100); + +There are also two ways to translate the 'and exit --#10' line, this depends on how many if statements are used. When using a single If statement (with two included 'else if' conditions), then you can translate 'and exit' as shown below: + + // and exit --#10 + System.exit(0); + +Alternatively, if you choose to use two if statements, then you can use a Java 'break' statement rather than 'System.exit(0)' to exit the program on the winning condition. +*** +### Viedo Recap: HiLow +Teacher preparation video HiLow recipe recap linked below. +“HiLow” + +Also, new teacher tip video 'How to use the Eclipse Debugger' (shown with the HiLow Variation) linked below. +https://www.youtube.com/watch?v=M8F6ziuccmw +*** +## Part 2 – Variation: HiLow +To kick off this section, you may choose to use the TKP Kata Question: + +_"How would you make sure that the guess is a positive number?"_ + +See the TKP Instructional Design (Teaching Variation) section for more information. + +Elicit from kids – _what features are there?_ +Example (with all later steps completed): + +Feature - Value +Text of questions - i.e. "What is your guess?" +Answer - Integer (40) +Number of Times Guess - 8 +Range of possible guesses - any integer + +### Variation Preparation +1. Prepare and then update the text of questions +Easy to change right now +Change to update the game - can make it funny +Run, see that it’s the same. [THIS IS IMPORTANT.] +Put X in “prepare” for 'text of questions'. +Can change text of input questions and messages out (including adding error messages - i.e. 'you can't guess more than 100 silly...', etc) + +2. Prepare and then update answer +Simple refactoring. Go to where it says 40, highlight, right click, refactor, extract local +variable. +Name it “answer” +Run – show that it does exactly the same thing. +[Don’t explain everything here – just show that it runs.] +X it off in the graph. + +3. Prepare and update the number of attempts to guess +_Which line determines this? the for loop stop value_ +You are just checking for understanding +Go back to grid, X it off + +4. Range of possible guesses +Can verify that currently the guess can be ANY integer, or within a range of integers (using additional conditional logic, i.e. additional and/or nested 'if' blocks) +Can change number of guesses allows and wrap in an if-block to select easy, medium or hard game (with progressively fewer guesses possible) + + +### Sample Variation Grid + +| Feature | Value | Refactor | +| ------ | ------ | -----: | +| Number of Guesses | 8 | no | +| Guess Value | number | no | +| Answer Value | number | no | +| Guess Value Range | integers | positive integers only | +| Guess Values | as above | reduce range of possible inputs | +| Guess Value Message | none | custom | +| Program Exit Point | simple | with message | + +*** +## Part 3 – Quiz: HiLowQuiz.java + +Working with Tortoise methods, such as getX( ), getY( ), and detail -- includes 'turn to the left' and more to verify that kids are actually reading the English comments before they translate into Java +*** +## Part 4 – **Recipe: ConcentricLoop** +Combines nested for loops with if statement and introduces scope of variables in loops, i.e. 'i' in first for loop and 'j' in nested for loop. +*** +## Part 5 – Recipe: ChooseYourOwnAdventure.java + +Open “ChooseYourOwnAdventure” +Each kid is on a single computer or this can be done in pairs if you prefer. + +This recipe uses a new type of comparision in the if clauses - specifically it uses the syntax: + "string1".equalsIgnoreCase(string2). + +This recipe teaches 'control of (program) flow' via complex conditional logic. Concepts included are these: +- Conditionals (if...elseif...else) +- Nested Conditionals (if....if...) +- Redirect to main method + +Also using methods to encapsulate reused code is demonstrated by both having kids write code and then extract it as a method (and then reuse that method elsewhere in the code) and also by introducing the idea of convenience methods for repeated code. Convenience methods represent code libraries that are used in production code to produce more human-readable code, particularly in cases of long methods/classes. + +The convenience methods used are as follows: + MessageBox.showMessage(message); --> tellMoreStory("blah..."); + MessageBox.askForInput(question); --> askAQuestion("blah..."); + +Other teaching tips: if the students are having difficulty, be sure to have them 'match' the braces for their 'if' statements. If you feel comfortable, you may want to add a breakpoint (click in the left margin on the code editor window on a line to 'break' [or stop] during execution of code on and then run the code in debug mode to open the debugger. Here's a link to a short tutorial on how to use the debugger - http://www.vogella.com/tutorials/EclipseDebugging/article.html + +*** +##Part 6 – Deep Dive: DeepDive03Ifs.java +Covers conditional logic, various implementations of 'if...' clauses + +### SETUP +Chairs at front, circle/oval/whatever – computer at desk to the side. + +Give kids post-its. +Each kid writes an observation and the last thing they just did. No talking – they just write. Then collect, and read them to the class. +PROCESS +When going through Deep Dive, one student will sit @ computer, another will be standing and will tell them what to type. +After each test, standing student gives observation (/explains why they entered what they did), then they rotate. +If they ask “Does it work if…” then try it and see! +SHOW THEM THE PROCESS +*** +## Part 7 – Worksheet: +Print '3_HiLowWorksheet.docx' and have the kids complete it. +*** + diff --git a/tkp-lesson-plans/course04.md b/tkp-lesson-plans/course04.md new file mode 100644 index 00000000..00dea8e7 --- /dev/null +++ b/tkp-lesson-plans/course04.md @@ -0,0 +1,112 @@ +# Teaching TKPJava Course 04 - Mastery Unit +Classes, Methods, For Loops, Variables, If Statements + + +_Objects, Methods and For Loops_ +*** +## Preparing to Teach this Course +| Every Course | Recipes in this Course | +|--------------------------------------------------------------|------------------------------| +| :hourglass: **Install** the [TKPJava courseware](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java#get-started-with-tkp) | **1**. PentagonCrazy - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section04mastery/PentagonCrazy.java) +| :green_book: **Read** this lesson plan page | **2**. PentagonCrazyQuiz - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section04mastery/PentagonCrazyQuiz.java) +| :computer: **Code** the recipes yourself | **3**. DigiFlower - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section04mastery/DigiFlower.java) | +| :bulb: **Review** the [TKPJava Language pptx](http://www.slideshare.net/lynnlangit/tkpjava-teaching-kids-programming-core-java-langauge-concep) | **4**. DigiFlowerVariation - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section04mastery/DigiFlowerVariation.java) | +| :fax: **Print** [the worksheet / also keyboard shortcuts cheat sheet](https://www.dropbox.com/s/9qwbv48p8lmx4nj/TKP-Worksheets.zip?dl=0) | **5**. KnottedRing - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section04mastery/KnottedRing.java) | +| :fax: **Review** the main [recipe worksheet](https://www.dropbox.com/s/9qwbv48p8lmx4nj/TKP-Worksheets.zip?dl=0) | **6**. BackgroundPhoto - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section04mastery/BackgroundPhoto.java) | +| :swimmer: | **7**. DeepDive04 - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section04mastery/DeepDive04Mastery.java) | + + +*** +## Part 1 - **Recipe: Pentagon Crazy** +This recipe is the first in this course. This course contains practices which review concepts that the students have already been introduced to in TKP Courses 1-3. + +### LINE NOTES + +The first review concept is the multi-step creation of variables. Remind students to use the 'fake it until you make it' technique. They will use this first on the length of a side by using a actual number, i.e. 42. Also remind the students that they should not delete the English as they have not finished translating it into Java. + +The line 'the current length of a side' - the kids should be using the refactoring 'extract variable' to create the variable length. You may have to help them to find the correct variable from the for loop. + +```java + int length = 1; +``` + +Do another 'fake' on the setPenColor (reinforces) with any color, then follow the info below. +The only tricky lines are the two shown below as they introduce a variation on the concept of passing parameters to methods using objects rather than simple variables or primitives (strings or ints): + + Tortoise.setPenColor(ColorWheel.getNextColor()); + Tortoise.setPenWidth(Tortoise.getPenWidth() + 1.0); + +Also this recipe is designed to reinforce using the 'extract method' tool in Eclipse - you should verify that students understand HOW and WHY they are extracting several methods in this recipe. The core concept is that well-written methods should be concise (do one thing) so that those methods are readable, have fewer bugs, are easier to maintain and update. +*** +### Video Recap: Pentagon Crazy +Video for teacher preparation +“Pentagon + +*** +### Variation Grid: Pentagon Crazy + +| Feature | Value | Refactor | +| ------ | ------ | -----: | +| Sides | 5 | no | +| Length | i | no | +| Color | ColorWheel | no | +| Rotation | 1 | no | +| Width | 1-4 | no | +| Background | SolidWhite (default) | expose default | +| Number of LInes | 200 | no | + +*** + +## Part 2 – Quiz: PentagonCrazyQuiz.java + +Cmd-shift-T: PCQ (PentagonCrazyQuiz) +This quiz verifies that kids can create a method (by using the 'refactor>extract method' in Eclipse and also can use (or call) an existing method. Also the colors passed in to the quiz are used in creating the 'reward shape'. After kids PASS all 4 questions, they can alter the color values, which will FAIL the quiz questions, but will change the reward shape colors. +*** +## Part 3, 4 and 5 – Extra Recipes: DigiFlower.java and BackgroundPhoto.java + + +See the TKP Instructional Design (Teaching Variation) section for more information. +In DigiFlower we introduce the idea of a group or list of variables by providing the kids with a list of Colors from the Java Color library, which are mapped to TKPPenColors for the ColorWheel. As with many TKP lessons, we first show the kids the code pattern and have them use this code. We do this because this is a common code pattern and also in TKP Course 5 kids will create and use a custom list to hold colors that is a different kind of list (here it's and abstraction over the Java ArrayList (using the TKPColorWheel) in Course 5 we will use the Java HashMap and in general in Course 5 we cover Java collections more extensively. + +There is a also a DigiFlowerVariation. It uses more complex math in the loop to render a more intricate pattern. + +To kick off this section, you may choose to use the TKP Kata Question: + +_"How would you change the shaper of a flower petal?"_ +*** +## Part 6 – Recipe: KnottedRing.java + +This is a review recipe - there is a reinforcement of a 'deliberate' error (or exception) that the students saw in an earlier recipe (Spiral). This 'error' is when the students try to 'get the next color' from the ColorWheel before they have added any colors to the wheel. + +The subtle difference in this error is that we do continue to show a custom error message i.e. 'I call shinanigans, there are no colors on the ColorWheel' (rather than the default message which would show a array out of bounds exception for the ArrayList object (upon which the ColorWheel is derived). However, unlike in the Spiral recipe, where we 'elevated' the custom error message to a Message Box (to make sure the kids see it), in this case, we've let the error message show up in the default location (that Console window at the bottom of the IDE). This is intentional. + +At this point the kids should have the habit of READING the error messages that show up in the Console so that they can understand and fix programming errors. +*** +## Part 7 – Deep Dive: DeepDive04 + +### SETUP +Chairs at front, circle/oval/whatever – computer at desk to the side. + +PROCESS +When going through Deep Dive, one student will sit @ computer, another will be standing and will tell them what to type. Encourage them the run each test FIRST to get more information about what change they need to make to get the test to pass. + +After each test passes (green bar in the result), the standing student gives observation (/explains why they entered what they did and what s/he learned), then they rotate. +If they ask “Does it work if…” then try it and see! + +In this DeepDive we are reinforcing these concepts: +1) Each variable has a type +2) Types explored are Integer, Double, String, Number and Object +3) 'Light' introduction to type inheritance via Number and Object +4) Variable initializers and type creation, i.e. + + Number myNumber = 2; //produces an Integer-typed variable + Number1 myNumber1 = 2.1 //produces a Double-typed variable + +5) Type conversion methods by example (i.e. to toString() method and others) +6) Operations on variables of same or mixed types (i.e. addition, division, concatenation) + +*** +## Part 8 – Worksheet: 4_PentagonCrazyWorksheet.docx + +Print this worksheet +*** diff --git a/tkp-lesson-plans/course05.md b/tkp-lesson-plans/course05.md new file mode 100644 index 00000000..b3b75bf6 --- /dev/null +++ b/tkp-lesson-plans/course05.md @@ -0,0 +1,107 @@ +# Teaching TKPJava Course 05 - Recursion + + +_Working with Recursion and Introducing Collections with HashMaps_ +*** +### Preparing to Teach this Course + +| Every Course | Recipes in this Course | +|--------------------------------------------------------------|------------------------------| +| :hourglass: **Install** the [TKPJava courseware](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java#get-started-with-tkp) | **1**. TurtleTree - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section05recursion/TurtleTree.java) | +| :green_book: **Read** this lesson plan page | **2**. TurtleTreeVariation - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section05recursion/TurtleTreeVariation.java) | +| :computer: **Code** the recipes yourself | **3**. TreeQuiz - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section05recursion/TreeQuiz.java) | +| :bulb: **Review** the [TKPJava Language pptx](http://www.slideshare.net/lynnlangit/tkpjava-teaching-kids-programming-core-java-langauge-concepts) | **4**. SpiderWeb - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section05recursion/SpiderWeb.java) | +|:fax: **Print** the [worksheet & keyboard shortcuts cheat sheet ](https://www.dropbox.com/s/9qwbv48p8lmx4nj/TKP-Worksheets.zip?dl=0) | **5**. RecursiveSquare - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section05recursion/RecursiveSquare.java) | +| :bulb: **Review** the recipe / lesson answer files | **6**. DeepDive05 - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section05recursion/DeepDive05Recursion.java) | + + +*** +## Part 1 - **Recipe: Turtle Tree** +-Have them read the line out loud. +-Guide them to figuring out the code themselves, to whatever extent possible. +-Once they figure it out, MAKE SURE THEY RUN THE CODE BEFORE PROCEEDING. (Use http://virtualproctor-tkp.appspot.com/ to show student windows on screen when they close) + +####Teacher notes +-Red box will kill the program. +-XX will reset the program, if only ONE is running. (useful if machine is being weird.) + +### LINE NOTES +Concept reinforced here is 'extract method'. Recursion is introduced through recipe translation. You can complete the conditional portion of this recipe using multiple 'If' statements (for example by using the pattern shown below) - this solution is also shown in the video: + + if (length == 10) { Tortoise.setPenColor(PenColors.Browns.Brown); //etc + +An alternative is to use a collection. This is due to the quantity of If statements needed to satisfy the logic. We recommend using the HashMap object for this. Alternatively, you can introduce the HashMap as refactoring (of the multiple 'if' statements during the variation for this recipe. + +The Hashmap is the first introduction of a collection object. Use of a HashMap is shown in the lines below (solution to the AdjustColor method): + + HashMap colors = new HashMap(); + colors.put(10, Colors.Greens.Lime); + colors.put(20, Colors.Greens.ForestGreen); + colors.put(30, Colors.Greens.DarkGreen); + colors.put(40, Colors.Greens.Olive); + colors.put(50, Colors.Browns.Sienna); + colors.put(60, Colors.Browns.SaddleBrown); + +To use the values in the HashMap, you'll need to call the 'get' method on it. This code is shown below: + + Tortoise.setPenColor(colors.get(branchLength)); + +### Video Recap: TurtleTree Recap +Video for teacher preparation +“Turtle + +*** +## Part 2 – Variation: Turtle Tree +To kick off this section, you may choose to use the TKP Kata Question: + +_"How would you make a second tree?"_ + +Example variation shows drawing more than one tree (extract method), also changing properties, background color, branch color, branch width. Explore changing the HashMap key (integer) values to let kids 'see' how the recursive calls affect the color(s) of the trees. + +*** +## Part 3 – Quiz: TreeQuiz.java + +Cmd-shift-T: TQ (TreeQuiz) + +Quiz questions 3 and 4 validate the HashMap concept using the pre-created object called 'angles' and the HashMap method 'put' for the (Key, Value) arguments. + + //question 3 - don't forget to refactor to extract the method + angles.put(turn,90); + + //question 4 - don't forget to refactor to extract the method + angles.put(5,36) +*** +## Part 4 – Recipe: SpiderWeb.java +This recipes uses Doubles rather than Integers for precision. Have the kids point out the recursion, by noting which methods call which other methods . This is a also a great recipe to use the Java debugger to have the kids 'see' the program execution flow. + +Note: Thanks to Katrina Owen for authoring the SpiderWeb recipe. + +*** +## Part 5 – Recipe: RecursiveSquare.java +As with the SpiderWeb recipe, this is another great one to use the debugger to show the kids the program flow. Again, you may want to ask the kids 'which method(s) call themselves and how many times do they do so?' + +Note: Thanks to Matt Ballin for authoring the RecursiveSquare recipe. + +*** + +## Part 6 – Deep Dive: DeepDive05Recursion + +### SETUP +Chairs at front, circle/oval/whatever – computer at desk to the side. +When going through Deep Dive, one student will sit @ computer, another will be standing and will tell them what to type. +After each test, standing student gives observation (/explains why they entered what they did), then they rotate. +If they ask “Does it work if…” then try it and see! + +The concepts taught here are as follows: +1) Chained methods, that is Tortoise.firstMethod().secondMethod(params); +-we created the new method .getCursor specifically for this deepDive +2) Collections - HashTables - using get/put with typed key/value pairs +3) Collections - Arrays - zero-based retrieval +4) Collections - Lists - as above +*** +### Part 7 – Worksheet: + +Print the '5_TurtleTreeWorksheet.docx' +*** + + diff --git a/tkp-lesson-plans/course06.md b/tkp-lesson-plans/course06.md new file mode 100644 index 00000000..074be604 --- /dev/null +++ b/tkp-lesson-plans/course06.md @@ -0,0 +1,122 @@ +# Teaching TKPJava Course 06 - MVC (Model-View-Controller) + + +_More on String Concatenation, Message Box - Using MVC (as a variation)_ +*** +##Preparing to Teach this Course +| Every Course | Recipes in this Course | +|--------------------------------------------|--------------------------| +| :hourglass: **Install** the [TKPJava courseware](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Java#get-started-with-tkp) | **1**. AdLibs - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section06modelviewcontroller/AdLibs.java) | +| :green_book: **Read** this lesson plan page | **2**. ExceptionalAdLibsVariation - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section06modelviewcontroller/ExceptionalAdLibsVariation.java) | +| :computer: **Code** the recipes yourself | **3**. AdLibsRtf - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section06modelviewcontroller/AdLibsRtf.java) | +| :bulb: **Review** the [TKPJava Language pptx](http://www.slideshare.net/lynnlangit/tkpjava-teaching-kids-programming-core-java-langauge-concepts) | **4**. AdLibsQuiz- [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section06modelviewcontroller/AdLibsQuiz.java) | +| :fax: **Print** the main [recipe worksheet](https://www.dropbox.com/s/9qwbv48p8lmx4nj/TKP-Worksheets.zip?dl=0) | **5**. DeepDive06 - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section06modelviewcontroller/DeepDive06ModelViewController.java) | +| :bulb: **Review** the recipe / lesson answer files | **6**. OneFishTwoFish - [answer](https://github.com/TeachingKidsProgramming/TeachingKidsProgramming.Source.Java/blob/master/src/main/java/org/teachingkidsprogramming/recipes/completed/section06modelviewcontroller/OneFishTwoFish.java) | + + +*** +## Part 1 - **Recipe: Ad Libs** + +Pretty basic recipe, but fun! String concatenation requires careful reading of the English and using quotes and concatenation characters ('+') correctly. + +We are also reinforcing the creation and use of variables with the use of 'current{word}' repeatedly in this recipe. + + //Ask the user to enter an adverb, save it as currentAdverb --#2 + String currentAdverb = MessageBox.askForTextInput("What is the adverb?"); + +We layer the string concatenation practice on top of the use of mutiple variables, for example: + + //Add the words "I woke " + currentAdverb + ". " to the currentStory --#3 + currentStory = currentStory + "I woke " + currentAdverb + ". "; + +### Video Recap: AdLibs Recap +Video recap for teacher preparation. + +“Ad + +*** + +## Part 2 - Variation: ExceptionalAdLibsVariation +To kick off this section, you may choose to use the TKP Kata Question: + +_"How would you make sure that the person telling your story did NOT enter in a number?"_ + +In this variation, we've added conditional logic to test for valid input values. Keeping this simple, we raise 'psuedo' exception messages in Message Boxes, rather than the more formal method of using try...catch w/Java exception handers. + +Also we introduce the first RegEx expression in the '_adverb.matches("[\\d]*")) argument. + +Be sure to point out the the use of 'If' statements and you may want to draw out the program control of flow mapping. + +We also refactored to include convenience methods, i.e. 'askForValueAgain( )....' + +## Part 3 – Variation: AdLibs with .rtf file + +A simple analogy to explain MVC is this: +_The Model is the food, the View is the plate and the Controller is the chef._ + +This is lead as a ‘follow the leader’ style exercise. Open Word or something to scribble in. Make a grid, add columns for feature, value; ask the kids: + +_which line(s) of code in the original AdLibs recipe create the model, which create the view and which create the controller?_ + +Answers: + +1. The Model or Data model is the concatenated string ("currentStory") +2. The View is the MessageBox in the recipe +3. The Controller is the .showMessage ( ) method in the recipe + +In the Variation, several new concepts are introduced: + + - to update the Model, create the **Words class** which holds the data Model - you will have to add a new class for this data + - to update the Parser object, which acts as a controller - use the .parseRtfFile (templateFilename, data); method + - to update the View object, which is the viewer - use the .displayRtfFile (model); method + These objects re-purpose the basic Model which the kids already created in the core recipe. + +The View object uses uses a the template file 'view.rtf' and which contains string replacement parameters, designated by the syntax {parameterName} as shown below. This template file (view.rtf) is compiled as a resource in the TKP.jar file. + + Today I woke {adverb}. Then I {edVerb} my {bodyPart}. + +Variation results: + +1. The Model (originally the concatenated string) -> becomes the Words class +2. The View (MessageBox) -> becomes an RTF file via the Viewer class, using the display RTF file method (using the template file and passing the parameter values [strings] via the template placeholders +3. The Controller (.showMessage ( ) ) -> becomes a Parser, using the parse RTF method + +### Alternate Variations + +For classes that would be better served by simpler variations than the MVC version listed above, teachers may wish to use the guidance provided below. + +New column: “Simple changes” +Add one more column: “Cool changes” +Can change anything, but needed to prepare before we mess around. + +Could add one or more Integers, i.e. number + 'number of bodyParts' to explore concatenation with variables of Integer type being converted and concatenated to variables of String type such as below: + + String myString = " body parts"; + Integer myNumber = 5; + result = myNumber + myString; + System.out.println(result); +*** + +## Part 4 – Quiz: AdLibsQuiz +concepts tested include the following: +Question 1 & 2) String concatenation (variations of such) +Question 3) MVC - implementing a custom parser - + hint: use Parser.parse(