├── .nojekyll ├── kiss.jar ├── src └── main │ └── java │ └── kiss │ ├── Makefile │ └── util │ ├── Makefile │ ├── VerifyRuntimeException.java │ ├── TestApp.java │ ├── Test.java │ ├── RNG.java │ ├── PortKey.java │ ├── TestRNG.java │ ├── AutoListener.java │ ├── TestEvent.java │ ├── TestIO.java │ ├── VerifyOutputStream.java │ ├── TestCipher.java │ ├── TestAs.java │ ├── TestRun.java │ ├── Run.java │ ├── Cipher.java │ └── Reflect.java ├── java-kiss.png ├── kiss-with-tests.jar ├── kiss.jar.sha256 ├── kiss-with-tests.jar.sha256 ├── examples ├── hi │ ├── README.md │ ├── Makefile │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── App.java │ └── pom.xml ├── events │ ├── README.md │ ├── Makefile │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── App.java │ └── pom.xml ├── fall │ ├── README.md │ ├── Makefile │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── App.java │ └── pom.xml ├── helloworld │ ├── README.md │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── App.java │ ├── Makefile │ └── pom.xml ├── rolls │ ├── README.md │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── App.java │ ├── Makefile │ ├── rolls.csv │ └── pom.xml ├── prime │ ├── README.md │ ├── Makefile │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── App.java ├── rockpaperscissors │ ├── README.md │ ├── Makefile │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── App.java │ └── pom.xml ├── craps │ ├── README.md │ ├── Makefile │ ├── src │ │ └── main │ │ │ └── java │ │ │ ├── Die.java │ │ │ └── App.java │ └── pom.xml └── basics │ ├── Makefile │ └── pom.xml ├── katas ├── bowl │ ├── README.md │ ├── Makefile │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── App.java ├── bus │ ├── README.md │ ├── Makefile │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── App.java ├── hi │ ├── README.md │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── App.java │ ├── Makefile │ └── pom.xml ├── branches │ ├── README.md │ ├── Makefile │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── App.java └── methods │ ├── README.md │ ├── Makefile │ ├── src │ └── main │ │ └── java │ │ └── App.java │ └── pom.xml ├── dieharder ├── runtests ├── Makefile ├── runtest ├── src │ └── App.java ├── README.md ├── rng-2.log ├── rng-3.log ├── rng-4.log └── rng-1.log ├── pi ├── examples │ ├── blink │ │ ├── bug │ │ │ ├── Makefile │ │ │ └── src │ │ │ │ └── ChangeBug1.java │ │ ├── src │ │ │ └── main │ │ │ │ └── java │ │ │ │ └── App.java │ │ └── Makefile │ └── hi │ │ └── Makefile ├── src │ └── main │ │ └── java │ │ └── kiss │ │ └── pi │ │ ├── API.java │ │ └── util │ │ └── GPIO.java └── Makefile ├── .gitignore ├── Makefile ├── pom.xml ├── README.md └── LICENSE /.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kiss.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wmacevoy/kiss/HEAD/kiss.jar -------------------------------------------------------------------------------- /src/main/java/kiss/Makefile: -------------------------------------------------------------------------------- 1 | % : 2 | $(MAKE) -C ../../../.. $@ 3 | -------------------------------------------------------------------------------- /java-kiss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wmacevoy/kiss/HEAD/java-kiss.png -------------------------------------------------------------------------------- /src/main/java/kiss/util/Makefile: -------------------------------------------------------------------------------- 1 | % : 2 | $(MAKE) -C ../../../../.. $@ 3 | -------------------------------------------------------------------------------- /kiss-with-tests.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wmacevoy/kiss/HEAD/kiss-with-tests.jar -------------------------------------------------------------------------------- /kiss.jar.sha256: -------------------------------------------------------------------------------- 1 | SHA256(kiss.jar)= 0ae76433a43e2193df89243675ff95a105a7a69d1183be05142ba7f8a1e6ba1e 2 | -------------------------------------------------------------------------------- /kiss-with-tests.jar.sha256: -------------------------------------------------------------------------------- 1 | SHA256(kiss-with-tests.jar)= 4fa5a3ba67ee908fb2525537d6a0074ea3a1817bb1ae18b7328a57c0f44bdcc3 2 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/VerifyRuntimeException.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | public class VerifyRuntimeException extends RuntimeException { 4 | VerifyRuntimeException(String message) { 5 | super(message); 6 | } 7 | 8 | } 9 | -------------------------------------------------------------------------------- /examples/hi/README.md: -------------------------------------------------------------------------------- 1 | # hi - kiss example 2 | 3 | To build application to target directory: 4 | 5 | ```sh 6 | mvn compile 7 | ``` 8 | 9 | To run application after building: 10 | 11 | ```sh 12 | mvn -q exec:exec 13 | ``` 14 | -------------------------------------------------------------------------------- /examples/events/README.md: -------------------------------------------------------------------------------- 1 | # hi - kiss example 2 | 3 | To build application to target directory: 4 | 5 | ```sh 6 | mvn compile 7 | ``` 8 | 9 | To run application after building: 10 | 11 | ```sh 12 | mvn -q exec:exec 13 | ``` 14 | -------------------------------------------------------------------------------- /examples/fall/README.md: -------------------------------------------------------------------------------- 1 | # fall - kiss example 2 | 3 | To build application to target directory: 4 | 5 | ```sh 6 | mvn compile 7 | ``` 8 | 9 | To run application after building: 10 | 11 | ```sh 12 | mvn -q exec:exec 13 | ``` 14 | -------------------------------------------------------------------------------- /katas/bowl/README.md: -------------------------------------------------------------------------------- 1 | # bus - bus kata 2 | 3 | Replace the `// TODO` with Java code so all the tests pass. 4 | 5 | 6 | ```sh 7 | mvn compile 8 | ``` 9 | 10 | To run application after building: 11 | 12 | ```sh 13 | mvn -q exec:exec 14 | ``` 15 | -------------------------------------------------------------------------------- /katas/bus/README.md: -------------------------------------------------------------------------------- 1 | # bus - bus kata 2 | 3 | Replace the `// TODO` with Java code so all the tests pass. 4 | 5 | 6 | ```sh 7 | mvn compile 8 | ``` 9 | 10 | To run application after building: 11 | 12 | ```sh 13 | mvn -q exec:exec 14 | ``` 15 | -------------------------------------------------------------------------------- /katas/hi/README.md: -------------------------------------------------------------------------------- 1 | # hi - kiss kata 2 | 3 | Replace the `// TODO` with Java code so all the tests pass. 4 | 5 | 6 | ```sh 7 | mvn compile 8 | ``` 9 | 10 | To run application after building: 11 | 12 | ```sh 13 | mvn -q exec:exec 14 | ``` 15 | -------------------------------------------------------------------------------- /dieharder/runtests: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | n=4 4 | 5 | for i in $(seq 1 $n) 6 | do 7 | ./runtest $i & 8 | p[${i}]=$! 9 | done 10 | 11 | for i in $(seq 1 $n) 12 | do 13 | wait ${p[$i]} 14 | done 15 | 16 | ruby merge.rb $n > rngs.csv 17 | 18 | -------------------------------------------------------------------------------- /examples/helloworld/README.md: -------------------------------------------------------------------------------- 1 | # Hello World - kiss example 2 | 3 | To build application to target directory: 4 | 5 | ```sh 6 | mvn compile 7 | ``` 8 | 9 | To run application after building: 10 | 11 | ```sh 12 | mvn -q exec:exec 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /pi/examples/blink/bug/Makefile: -------------------------------------------------------------------------------- 1 | bin/ChangeBug1.class : src/ChangeBug1.java 2 | javac -cp /opt/pi4j/lib/'*' -d bin src/ChangeBug1.java 3 | 4 | bug1: bin/ChangeBug1.class 5 | echo "no GPIO STATE CHANGE when state changes..." 6 | sudo java -cp bin:/opt/pi4j/lib/'*' ChangeBug1 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *~ 3 | 4 | # Mobile Tools for Java (J2ME) 5 | .mtj.tmp/ 6 | 7 | # Package Files # 8 | *.jar 9 | *.war 10 | *.ear 11 | 12 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 13 | hs_err_pid* 14 | 15 | # Maven 16 | target/ 17 | settings.xml 18 | -------------------------------------------------------------------------------- /examples/helloworld/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | void testRun() { 5 | try (Close out = outExpect("Hello, World!")) { 6 | run(); 7 | } 8 | } 9 | 10 | void run() { 11 | println("Hello, World!"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/rolls/README.md: -------------------------------------------------------------------------------- 1 | # rolls - kiss die roll example 2 | 3 | To build application to target directory: 4 | 5 | ```sh 6 | mvn compile 7 | ``` 8 | 9 | To run application after building: 10 | 11 | ```sh 12 | mvn -q exec:exec 13 | ``` 14 | 15 | This creates a rolls.csv file with 100 die roll samples. 16 | 17 | -------------------------------------------------------------------------------- /katas/branches/README.md: -------------------------------------------------------------------------------- 1 | # method - kiss kata 2 | 3 | Replace the `// TODO` with Java code so all the tests pass. This introduces 4 | the idea of a method/function in a java program. 5 | 6 | 7 | ```sh 8 | mvn compile 9 | ``` 10 | 11 | To run application after building: 12 | 13 | ```sh 14 | mvn -q exec:exec 15 | ``` 16 | -------------------------------------------------------------------------------- /katas/methods/README.md: -------------------------------------------------------------------------------- 1 | # method - kiss kata 2 | 3 | Replace the `// TODO` with Java code so all the tests pass. This introduces 4 | the idea of a method/function in a java program. 5 | 6 | 7 | ```sh 8 | mvn compile 9 | ``` 10 | 11 | To run application after building: 12 | 13 | ```sh 14 | mvn -q exec:exec 15 | ``` 16 | -------------------------------------------------------------------------------- /examples/prime/README.md: -------------------------------------------------------------------------------- 1 | # prime - test driven development 2 | 3 | To build application to target directory: 4 | 5 | ```sh 6 | mvn compile 7 | ``` 8 | 9 | To run application after building: 10 | 11 | ```sh 12 | mvn -q exec:exec 13 | ``` 14 | 15 | The "Homework" assignment is to define isPrime so it will all the tests. 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/rockpaperscissors/README.md: -------------------------------------------------------------------------------- 1 | # rolls - kiss rock paper scissors example 2 | 3 | To build application to target directory: 4 | 5 | ```sh 6 | mvn compile 7 | ``` 8 | 9 | To run application after building: 10 | 11 | ```sh 12 | mvn -q exec:exec 13 | ``` 14 | 15 | This is a computer vs person rock-paper scissors console game. 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/TestApp.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | class TestApp { 4 | int constructed = 0; 5 | TestApp() { ++constructed; } 6 | 7 | int tested = 0; 8 | void testEd() { ++tested; } 9 | 10 | int ran = 0; 11 | 12 | void run() { ++ran; } 13 | 14 | int closed = 0; 15 | void close() { ++closed; } 16 | } 17 | -------------------------------------------------------------------------------- /examples/rolls/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | void run() { 5 | outOpen("rolls.csv"); 6 | println("i,d1,d2,sum"); 7 | for (int i=1; i<=100; ++i) { 8 | int d1=random(1,6); 9 | int d2=random(1,6); 10 | int sum=d1+d2; 11 | println(i,d1,d2,sum); 12 | } 13 | outClose(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/craps/README.md: -------------------------------------------------------------------------------- 1 | # craps - kiss craps 2 | 3 | Shows how PRNG is repeatable for tests, but random for run. 4 | 5 | It also illustrates testing subcomponents by wrapping the 6 | creation of these objects with `test()`. 7 | 8 | To build application to target directory: 9 | 10 | ```sh 11 | mvn compile 12 | ``` 13 | 14 | To run application after building: 15 | 16 | ```sh 17 | mvn -q exec:exec 18 | ``` 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/Test.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import static kiss.API.*; 4 | 5 | public class Test { 6 | void testIO() { test(new TestIO()); } 7 | void testAs() { test(new TestAs()); } 8 | void testRNG() { test(new TestRNG()); } 9 | void testRun() { test(new TestRun()); } 10 | void testAESPRNG() { test(new TestAESPRNG()); } 11 | void testCipher() { test(new TestCipher()); } 12 | void testEvent() { test(new TestEvent()); } 13 | } 14 | -------------------------------------------------------------------------------- /pi/examples/blink/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | import static kiss.pi.API.*; 3 | 4 | class App { 5 | public static final int LED_PIN = 7; 6 | 7 | boolean on; 8 | 9 | void run() { 10 | setup(); 11 | while (true) { 12 | loop(); 13 | } 14 | } 15 | 16 | void setup() { 17 | on = false; 18 | pinMode(LED_PIN,OUTPUT_LOW); 19 | } 20 | 21 | void loop() { 22 | on = !on; 23 | digitalWrite(LED_PIN,on); 24 | pause(1.0); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /katas/hi/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | void testKata1() { 5 | for (String name : new String[] { "Alice", "Bob", "World" }) { 6 | try (Close in = inProvide(name)) { 7 | try (Close out = outExpect("Hello, " + name + "!")) { 8 | hi(); 9 | } 10 | } 11 | } 12 | } 13 | 14 | void hi() { 15 | // get a name, and tell them hello. 16 | // TODO 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/RNG.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | public class RNG { 4 | public static final AESPRNG RANDOM = new AESPRNG(); 5 | public static final void seed() { RANDOM.seed(); } 6 | public static final void seed(double value) { 7 | RANDOM.seed(Double.doubleToLongBits(value)); 8 | } 9 | public static final int random(int a, int b) { 10 | return RANDOM.nextInt(a,b); 11 | } 12 | public static final double random() { 13 | return RANDOM.nextDouble(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /katas/bus/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /katas/hi/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /examples/craps/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /examples/fall/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /examples/hi/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /examples/prime/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /examples/rolls/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /katas/bowl/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /katas/branches/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /katas/methods/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /dieharder/Makefile: -------------------------------------------------------------------------------- 1 | all : jaesprng.log 2 | tmp/App.class : src/App.java 3 | if [ ! -d tmp ] ; then mkdir tmp ; fi 4 | javac -cp ../kiss/kiss.jar:tmp -d tmp -s src src/App.java 5 | 6 | jaesprng.log: tmp/App.class 7 | /bin/rm -rf tmp/jaesprng 8 | mkfifo tmp/jaesprng 9 | java -cp ../kiss/kiss.jar:tmp kiss.util.Run - > tmp/jaesprng & 10 | date -u > jaesprng.log 11 | nice time dieharder -a -g 201 -f tmp/jaesprng | tee -a jaesprng.log 12 | dd count=1 bs=1024 if=tmp/jaesprng of=/dev/null # close pipe 13 | /bin/rm -rf tmp/jaesprng 14 | 15 | urandom.log: 16 | date -u > urandom.log 17 | nice time dieharder -a -g 201 -f /dev/urandom | tee -a urandom.log 18 | -------------------------------------------------------------------------------- /examples/basics/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /examples/events/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /examples/helloworld/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp "../../kiss.jar" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | java -cp "../../kiss.jar:target/classes" kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | java -cp "../../kiss.jar:target/classes" kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /examples/craps/src/main/java/Die.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class Die 4 | { 5 | private int value; 6 | 7 | void roll() { value = random(1,6); } 8 | 9 | int getValue() { return value; } 10 | 11 | Die() { roll(); } 12 | 13 | void testDieStats() { 14 | int n=10000; 15 | int[] bins = new int[6]; 16 | for (int i=0; i $fifo & 29 | jpid=$! 30 | 31 | echo "jpid=$jpid" 32 | 33 | date -u > $log 34 | time dieharder -a -g 201 -f $fifo | tee -a $log 35 | kill $jpid 36 | 37 | -------------------------------------------------------------------------------- /pi/examples/blink/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../.. lib 7 | 8 | .PHONY: this 9 | this: 10 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 11 | javac -cp ../../../kiss.jar:../../kiss-pi.jar:/opt/pi4j/lib/'*' -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 12 | 13 | .PHONY: run 14 | run: 15 | sudo java -cp target/classes:../../../kiss.jar:../../kiss-pi.jar:/opt/pi4j/lib/'*' kiss.API 16 | 17 | .PHONY: test 18 | test: 19 | sudo java -cp target/classes:../../../kiss.jar:../../kiss-pi.jar:/opt/pi4j/lib/'*' kiss.API --norun 20 | 21 | .PHONY: clean 22 | clean: 23 | /bin/rm -rf target/* 24 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 25 | -------------------------------------------------------------------------------- /pi/examples/hi/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib this run 3 | 4 | .PHONY: lib 5 | lib: 6 | $(MAKE) -C ../../.. lib 7 | $(MAKE) -C ../.. lib 8 | 9 | .PHONY: this 10 | this: 11 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 12 | javac -cp "../../../kiss.jar:../../kiss-pi.jar:/opt/pi4j/lib/*" -d "target/classes" -s "src/main/java" $$(find "src/main/java" -regex '[^._].*\.java$$') 13 | 14 | .PHONY: run 15 | run: 16 | java -cp "../../../kiss.jar:target/classes:../../kiss-pi.jar:/opt/pi4j/lib/*" kiss.util.Run 17 | 18 | .PHONY: test 19 | test: 20 | java -cp "../../../kiss.jar:target/classes:../../kiss-pi.jar:/opt/pi4j/lib/*" kiss.util.Run --norun 21 | 22 | .PHONY: clean 23 | clean: 24 | /bin/rm -rf target/* 25 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 26 | -------------------------------------------------------------------------------- /pi/src/main/java/kiss/pi/API.java: -------------------------------------------------------------------------------- 1 | package kiss.pi; 2 | 3 | import kiss.pi.util.GPIO; 4 | 5 | public class API 6 | { 7 | public static final int INPUT = GPIO.INPUT; 8 | public static final int INPUT_PULLDOWN = GPIO.INPUT_PULLDOWN; 9 | public static final int INPUT_PULLUP = GPIO.INPUT_PULLUP; 10 | public static final int OUTPUT_LOW = GPIO.OUTPUT_LOW; 11 | public static final int OUTPUT_HIGH = GPIO.OUTPUT_HIGH; 12 | 13 | public static final void pinMode(int pinNum, int mode) { 14 | GPIO.pinMode(pinNum,mode); 15 | } 16 | public static final void digitalWrite(int pinNum, boolean value) { 17 | GPIO.digitalWrite(pinNum,value); 18 | } 19 | public static final boolean digitalRead(int pinNum) { 20 | return GPIO.digitalRead(pinNum); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dieharder/src/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | import java.io.FileOutputStream; 4 | import java.io.OutputStream; 5 | import java.io.Closeable; 6 | 7 | class App { 8 | 9 | OutputStream open(String name) throws Exception { 10 | if (name.equals("-")) return System.out; 11 | return new FileOutputStream(name); 12 | } 13 | 14 | void run() throws Exception { 15 | long size = APP_ARGS.length > 1 ? asLong(APP_ARGS[1]) : Long.MAX_VALUE; 16 | kiss.util.AESPRNG rng = new kiss.util.AESPRNG(); 17 | byte[] block = new byte[1024*1024]; 18 | try (OutputStream out = open(APP_ARGS[0])) { 19 | while (size > 0) { 20 | int n = block.length; 21 | if (asLong(n) > size) { 22 | n = asInt(size); 23 | } 24 | rng.nextBytes(block,0,n); 25 | out.write(block,0,n); 26 | size -= n; 27 | } 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/fall/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | void testEarth() { 5 | double t=1; 6 | double g=9.8; 7 | double d_cm = 100*g; 8 | inProvide(t,g); 9 | outExpect("time(seconds)? gravity(meters/second^2)? " 10 | +"It fell 490 centimeters."); 11 | run(); 12 | outClose(); 13 | inClose(); 14 | } 15 | 16 | void testMoon() { 17 | double t=1; 18 | double g=1.6; 19 | double d_cm = 100*g; 20 | inProvide(t,g); 21 | outExpect("time(seconds)? gravity(meters/second^2)? " 22 | +"It fell 80 centimeters."); 23 | run(); 24 | outClose(); 25 | inClose(); 26 | } 27 | 28 | void run() { 29 | print("time(seconds)? "); 30 | double t = readDouble(); 31 | print("gravity(meters/second^2)? "); 32 | double g = readDouble(); 33 | double d =0.5*g*pow(t,2); 34 | println("It fell " + round(d*100) + " centimeters."); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dieharder/README.md: -------------------------------------------------------------------------------- 1 | # RNG Test 2 | 3 | ## You Don't Care 4 | 5 | This is just an internal detail about the library and has nothing to do with learning java. 6 | 7 | ## You are a developer and interested in the AESPRNG internal generator. 8 | 9 | This is a tiny project to test the AESPRNG against the dieharder randomness 10 | tests. It runs in linux or os x, assuming you have the kiss library in the 11 | parent directory and the dieharder test suite (sudo apt-get install 12 | dieharder/brew install dieharder) installed. 13 | 14 | ```bash 15 | ./runtests 16 | ``` 17 | 18 | Should make and run some tests. Check your process table (top/activity 19 | monitor) and make sure there are no leftover procesess or just reboot 20 | after you complete the tests. 21 | 22 | Notes 23 | 24 | * These tests take some time to run. 25 | * Because the p-values are uniformly distributed and there are so many tests, you should expect WEAK (1%) and possible FAIL (0.01%) tests, just not consistently on the same test. 26 | * `rng-*.log` are example log files. 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/PortKey.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import javax.crypto.spec.SecretKeySpec; 6 | 7 | /** 8 | * Created by wmacevoy on 10/12/16. 9 | */ 10 | 11 | public class PortKey implements kiss.API.Close { 12 | 13 | // forward portable to JDK 1.8 to destroy keys 14 | // but usable in older JDK's 15 | 16 | static final Method destroyKey; 17 | 18 | static { 19 | Method _destroyKey = null; 20 | try { 21 | _destroyKey = SecretKeySpec.class.getMethod("destroy"); 22 | } catch (Exception ex) { 23 | } 24 | destroyKey = _destroyKey; 25 | } 26 | 27 | static void destroy(SecretKeySpec key) { 28 | if (key != null && destroyKey != null) { 29 | try { 30 | destroyKey.invoke(key); 31 | } catch (Exception ex) { 32 | } 33 | } 34 | } 35 | 36 | public final SecretKeySpec data; 37 | 38 | public PortKey(SecretKeySpec _data) { 39 | data = _data; 40 | } 41 | 42 | public void close() { 43 | destroy(data); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/TestRNG.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import static kiss.API.*; 4 | 5 | class TestRNG { 6 | void testRandomIntRange() 7 | { 8 | int min = -2; 9 | int max = 7; 10 | boolean [] hits = new boolean[max-min+1]; 11 | for (int i=0; i < 1000; ++i) { 12 | int x = random(min,max); 13 | assert min <= x && x <= max; 14 | hits[x - min]=true; 15 | } 16 | for (int i=0; i to generate State messages, so 18 | // 19 | // * Any Light (or other objects with an receive(...)) can 20 | // listen to a Remote to receive State messages. 21 | // 22 | // * Remote can send(State msg) to send a message to all added 23 | // listeners. 24 | // 25 | class Remote extends Generator { 26 | void on() { send(State.on); } 27 | void off() { send(State.off); } 28 | } 29 | 30 | class App { 31 | void testHouse() { 32 | Light bedroomLight = new Light("bedroom"); 33 | Light kitchenLight = new Light("kitchen"); 34 | 35 | Remote remote = new Remote(); 36 | 37 | // connecting remote to lights... 38 | remote.addListener(bedroomLight); 39 | remote.addListener(kitchenLight); 40 | 41 | // and an arbitrary action (lambda function) 42 | remote.addListener((state)->println("sent " + state)); 43 | 44 | try (Close out = outExpect("light in bedroom is on",EOL, 45 | "light in kitchen is on",EOL, 46 | "sent on")) { 47 | remote.on(); 48 | } 49 | 50 | try (Close out = outExpect("light in bedroom is off",EOL, 51 | "light in kitchen is off",EOL, 52 | "sent off")) { 53 | remote.off(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/rockpaperscissors/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | enum Choice { Rock, Paper, Scissors, Quit } 5 | 6 | Choice computer; 7 | Choice person; 8 | 9 | void computerPick() { 10 | switch(random(1,3)) { 11 | case 1: computer = Choice.Rock; break; 12 | case 2: computer = Choice.Paper; break; 13 | case 3: computer = Choice.Scissors; break; 14 | } 15 | } 16 | 17 | void personPick() { 18 | person = null; 19 | while (person == null) { 20 | print("Rock, Paper, Scissors, or Quit? "); 21 | switch(readLine()) { 22 | case "Rock": person = Choice.Rock; break; 23 | case "Paper": person = Choice.Paper; break; 24 | case "Scissors": person = Choice.Scissors; break; 25 | case "Quit": person = Choice.Quit; break; 26 | } 27 | } 28 | } 29 | 30 | boolean beats(Choice a, Choice b) { 31 | switch(a) { 32 | case Rock: return b == Choice.Scissors; 33 | case Paper: return b == Choice.Rock; 34 | case Scissors: return b == Choice.Paper; 35 | } 36 | throw new Error("Inconceivable!"); 37 | } 38 | 39 | void resolveWinner() { 40 | print(person + " vs. " + computer + ": "); 41 | if (beats(person,computer)) { 42 | println("you win!"); 43 | } else if (beats(computer,person)) { 44 | println("computer wins!"); 45 | } else { 46 | println("tie."); 47 | } 48 | } 49 | 50 | void run() { 51 | for (;;) { 52 | computerPick(); 53 | personPick(); 54 | if (person == Choice.Quit) break; 55 | resolveWinner(); 56 | } 57 | println("Bye!"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /katas/methods/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | void bib() { 5 | print("bib"); 6 | } 7 | void bob() { 8 | print("bob"); 9 | } 10 | void boo() { 11 | print("boo"); 12 | } 13 | void bity() { 14 | print("bity"); 15 | } 16 | void space() { 17 | print(" "); 18 | } 19 | void line() { 20 | println(); 21 | } 22 | 23 | void bibbityBobbityBoop() { 24 | // TODO call methods above to pass test below. 25 | } 26 | 27 | void testBibbityBobbityBoop() { 28 | try (Close out = outExpect("bibbity bobbity boo",EOL)) { 29 | bibbityBobbityBoop(); 30 | } 31 | } 32 | 33 | void hello(String name) { 34 | println("Hello " + name); 35 | } 36 | 37 | void helloWorld() { 38 | // TODO: call the hello() method above to pass the test below 39 | } 40 | 41 | void testHelloWorld() { 42 | try (Close out = outExpect("Hello World!", EOL)) { 43 | helloWorld(); 44 | } 45 | } 46 | 47 | int sum(int a, int b) { 48 | return a+b; 49 | } 50 | 51 | int sum(int a, int b, int c, int d, int e) { 52 | // Write a single return expression using ONLY sum(X,Y) 53 | // (no explicit additions), that return the sum of 54 | // all five terms. 55 | } 56 | 57 | void checkRandomSum() { 58 | int x = random(-100,100); 59 | int y = random(-100,100); 60 | int z = random(-100,100); 61 | int t = random(-100,100); 62 | int s = random(-100,100); 63 | 64 | assert sum(x,y,z,t,s) == (x+y+z+t+s); 65 | } 66 | 67 | void testSum() { 68 | checkRandomSum(); 69 | checkRandomSum(); 70 | checkRandomSum(); 71 | checkRandomSum(); 72 | checkRandomSum(); 73 | checkRandomSum(); 74 | checkRandomSum(); 75 | checkRandomSum(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /pi/examples/blink/bug/src/ChangeBug1.java: -------------------------------------------------------------------------------- 1 | import com.pi4j.io.gpio.*; 2 | import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent; 3 | import com.pi4j.io.gpio.event.GpioPinListenerDigital; 4 | 5 | class ChangeBug1 { 6 | public static void main(String args[]) throws InterruptedException { 7 | System.out.println("<--Pi4J--> GPIO Listen Example ... started."); 8 | 9 | // modified because I could not figure out the pin numbering 10 | GpioFactory.setDefaultProvider(new RaspiGpioProvider(RaspiPinNumberingScheme.BROADCOM_PIN_NUMBERING)); 11 | final GpioController gpio = GpioFactory.getInstance(); 12 | 13 | 14 | // provision gpio pin #03 as an input pin with its internal pull down resistor enabled 15 | // pinMode(App.BUTTON_PIN,INPUT_PULLUP); 16 | //final GpioPinDigitalMultipurpose myButton = kiss.pi.util.GPIO.pin(App.BUTTON_PIN); 17 | final GpioPinDigitalInput myButton = gpio.provisionDigitalInputPin(RaspiBcmPin.GPIO_02, "myButton", PinPullResistance.PULL_UP); 18 | 19 | // set shutdown state for this input pin 20 | myButton.setShutdownOptions(true); 21 | 22 | // create and register gpio pin listener 23 | myButton.addListener(new GpioPinListenerDigital() { 24 | @Override 25 | public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { 26 | // display pin state on console 27 | System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState()); 28 | } 29 | 30 | }); 31 | 32 | System.out.println(" ... complete the GPIO #02 circuit and see the listener feedback here in the console."); 33 | 34 | // keep program running until user aborts (CTRL-C) 35 | while(true) { 36 | Thread.sleep(1000); 37 | System.out.println(myButton.getState()); 38 | } 39 | 40 | // stop all GPIO activity/threads by shutting down the GPIO controller 41 | // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) 42 | // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pi/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : clean lib examples test 3 | 4 | SRC:=$(shell find src/main/java -regex '[^._].*\.java$$') 5 | 6 | kiss-pi.jar: $(SRC) 7 | $(MAKE) -C .. lib 8 | /bin/rm -rf target/classes 9 | mkdir target/classes 10 | javac -Xlint:unchecked -cp ../kiss.jar:target/classes:/opt/pi4j/lib/'*' -d target/classes -s src/main/java $$(find src/main/java -regex '[^._].*\.java$$') 11 | cd target/classes; jar cf ../../kiss-pi.jar . 12 | 13 | %.sha256 : % 14 | openssl dgst -out $@ -sha256 $< 15 | 16 | .PHONY: lib 17 | lib : kiss-pi.jar kiss-pi.jar.sha256 18 | 19 | .PHONY: doc 20 | doc : 21 | mvn javadoc:javadoc 22 | 23 | .PHONY: verify 24 | verify: 25 | for file in kiss-pi.jar ; do \ 26 | if openssl dgst -sha256 "$$file" | diff -q - "$$file.sha256" ; \ 27 | then \ 28 | echo "$$file checksum matches $$file.sha256" ; \ 29 | fi; \ 30 | done 31 | 32 | .PHONY: examples 33 | examples: 34 | for dir in examples/*; do \ 35 | if [ -f "$$dir/Makefile" ] ; then \ 36 | echo "$$dir: make this"; \ 37 | $(MAKE) -C "$$dir" this ; \ 38 | fi ; \ 39 | done 40 | 41 | .PHONY: clean 42 | clean: # mvn clean 43 | /bin/rm -rf tmp/* target/* examples/*/target/* examples/*/tmp/* 44 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 45 | 46 | deploy: clean all 47 | git add -f kiss-pi.jar kiss-pi.jar.sha256 48 | git commit -m "deploy `date -u`" 49 | git push 50 | mvn clean 51 | mvn compile 52 | mvn deploy 53 | 54 | .PHONY: test 55 | test: self-test example-tests 56 | 57 | .PHONY: self-test 58 | self-test: 59 | java -cp target/classes kiss.util.Run --app kiss.util.Test 60 | 61 | .PHONY: example-tests 62 | example-tests: 63 | for dir in examples/*; do \ 64 | if [ -f "$$dir/Makefile" ] ; then \ 65 | echo "$$dir: make test"; \ 66 | $(MAKE) -C "$$dir" test ; \ 67 | fi ; \ 68 | done 69 | 70 | .PHONY: example-runs 71 | example-runs: 72 | for dir in examples/*; do \ 73 | if [ -f "$$dir/Makefile" ] ; then \ 74 | echo "$$dir: make run"; \ 75 | $(MAKE) -C "$$dir" run ; \ 76 | fi ; \ 77 | done 78 | 79 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/AutoListener.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | import java.util.HashMap; 6 | 7 | import kiss.API.Generator; 8 | import kiss.API.Listener; 9 | 10 | public class AutoListener implements Listener { 11 | private static final HashMap< Class, Class> unbox = new HashMap<>(); 12 | 13 | static { 14 | unbox.put(Boolean.class, boolean.class); 15 | unbox.put(Character.class, char.class); 16 | unbox.put(Byte.class, byte.class); 17 | unbox.put(Short.class, short.class); 18 | unbox.put(Integer.class, int.class); 19 | unbox.put(Long.class, long.class); 20 | unbox.put(Float.class, float.class); 21 | unbox.put(Double.class, double.class); 22 | } 23 | 24 | public static class Exception extends RuntimeException { 25 | 26 | Exception(java.lang.Exception cause) { 27 | super(cause); 28 | } 29 | } 30 | private Object object; 31 | private Method method; 32 | 33 | public AutoListener(Class type, Object _object) { 34 | try { 35 | object = _object; 36 | method = object.getClass().getDeclaredMethod("receive", type); 37 | method.setAccessible(true); 38 | } catch (NoSuchMethodException | SecurityException ex) { 39 | Class unboxed = unbox.get(type); 40 | if (unboxed != null) { 41 | try { 42 | method = object.getClass().getDeclaredMethod("receive", unboxed); 43 | method.setAccessible(true); 44 | return; 45 | } catch (NoSuchMethodException | SecurityException ex2) { 46 | throw new Exception(ex2); 47 | } 48 | } 49 | throw new Exception(ex); 50 | } 51 | } 52 | 53 | @Override 54 | public void receive(Message message) { 55 | try { 56 | method.invoke(object, message); 57 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 58 | throw new Exception(ex); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/hi/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-hi 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-jar-plugin 27 | 28 | 29 | 30 | true 31 | kiss.util.Run 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 1.5.0 40 | 41 | 42 | 43 | exec 44 | 45 | 46 | 47 | 48 | java 49 | 50 | -cp 51 | 52 | -ea 53 | kiss.util.Run 54 | --app 55 | App 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/basics/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-basics 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-jar-plugin 27 | 28 | 29 | 30 | true 31 | kiss.util.Run 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 1.5.0 40 | 41 | 42 | 43 | exec 44 | 45 | 46 | 47 | 48 | java 49 | 50 | -cp 51 | 52 | -ea 53 | kiss.util.Run 54 | --app 55 | App 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/craps/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-craps 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-jar-plugin 27 | 28 | 29 | 30 | true 31 | kiss.util.Run 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 1.5.0 40 | 41 | 42 | 43 | exec 44 | 45 | 46 | 47 | 48 | java 49 | 50 | -cp 51 | 52 | -ea 53 | kiss.util.Run 54 | --app 55 | App 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/events/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-events 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-jar-plugin 27 | 28 | 29 | 30 | true 31 | kiss.util.Run 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 1.5.0 40 | 41 | 42 | 43 | exec 44 | 45 | 46 | 47 | 48 | java 49 | 50 | -cp 51 | 52 | -ea 53 | kiss.util.Run 54 | --app 55 | App 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/fall/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-fall 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-jar-plugin 27 | 28 | 29 | 30 | true 31 | kiss.util.Run 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 1.5.0 40 | 41 | 42 | 43 | exec 44 | 45 | 46 | 47 | 48 | java 49 | 50 | -cp 51 | 52 | -ea 53 | kiss.util.Run 54 | --app 55 | App 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/prime/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-prime 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-jar-plugin 27 | 28 | 29 | 30 | true 31 | kiss.util.Run 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 1.5.0 40 | 41 | 42 | 43 | exec 44 | 45 | 46 | 47 | 48 | java 49 | 50 | -cp 51 | 52 | -ea 53 | kiss.util.Run 54 | --app 55 | App 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/rolls/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-rolls 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-jar-plugin 27 | 28 | 29 | 30 | true 31 | kiss.util.Run 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 1.5.0 40 | 41 | 42 | 43 | exec 44 | 45 | 46 | 47 | 48 | java 49 | 50 | -cp 51 | 52 | -ea 53 | kiss.util.Run 54 | --app 55 | App 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/rockpaperscissors/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-rockpaperscissors 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-jar-plugin 27 | 28 | 29 | 30 | true 31 | kiss.util.Run 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 1.5.0 40 | 41 | 42 | 43 | exec 44 | 45 | 46 | 47 | 48 | java 49 | 50 | -cp 51 | 52 | -ea 53 | kiss.util.Run 54 | --app 55 | App 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/TestEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 wmacevoy. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package kiss.util; 17 | 18 | import java.util.ArrayList; 19 | import kiss.API.Generator; 20 | 21 | /** 22 | * 23 | * @author wmacevoy 24 | */ 25 | public class TestEvent { 26 | 27 | static class L { 28 | 29 | ArrayList receivedStrings = new ArrayList(); 30 | 31 | void receive(String value) { 32 | receivedStrings.add(value); 33 | } 34 | ArrayList receivedIntegers = new ArrayList(); 35 | 36 | void receive(int value) { 37 | receivedIntegers.add(value); 38 | } 39 | ArrayList receivedDoubles = new ArrayList(); 40 | 41 | void receive(Double value) { 42 | receivedDoubles.add(value); 43 | } 44 | } 45 | 46 | static class GS extends Generator { 47 | 48 | void emit(String value) { 49 | send(value); 50 | } 51 | } 52 | 53 | static class GI extends Generator { 54 | 55 | void emit(int value) { 56 | send(value); 57 | } 58 | } 59 | 60 | static class GD extends Generator { 61 | 62 | void emit(Double value) { 63 | send(value); 64 | } 65 | } 66 | 67 | void testListen() { 68 | L el = new L(); 69 | GS gs = new GS(); 70 | GI gi = new GI(); 71 | GD gd = new GD(); 72 | gs.addListener(el); 73 | gi.addListener(el); 74 | gd.addListener(el); 75 | gs.emit("axe"); 76 | gi.emit(17); 77 | gd.emit(3.14); 78 | 79 | assert el.receivedDoubles.get(0) == 3.14; 80 | assert el.receivedIntegers.get(0) == 17; 81 | assert el.receivedStrings.get(0).equals("axe"); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all : lib examples test 3 | 4 | SRC:=$(shell find src/main/java -regex '[^._].*\.java$$') 5 | 6 | kiss.jar kiss-with-tests.jar : $(SRC) 7 | /bin/rm -rf target/classes/* 8 | if [ ! -d target/classes ] ; then mkdir -p target/classes ; fi 9 | javac -target 1.7 -source 1.7 -Xlint:unchecked -cp target/classes -d target/classes -s src/main/java $$(find src/main/java -regex '[^._].*\.java$$') 10 | cd target/classes; jar cvfe ../../kiss.jar kiss.API $$(find . -name '*.class' -and -not -iname 'test*') 11 | cd target/classes; jar cfe ../../kiss-with-tests.jar kiss.API . 12 | 13 | %.sha256 : % 14 | openssl dgst -out $@ -sha256 $< 15 | 16 | .PHONY: lib 17 | lib : kiss.jar kiss.jar.sha256 kiss-with-tests.jar kiss-with-tests.jar.sha256 18 | 19 | .PHONY: doc 20 | doc : 21 | mvn javadoc:javadoc 22 | 23 | .PHONY: verify 24 | verify: 25 | for file in kiss.jar kiss-with-tests.jar ; do \ 26 | if openssl dgst -sha256 "$$file" | diff -q - "$$file.sha256" ; \ 27 | then \ 28 | echo "$$file checksum matches $$file.sha256" ; \ 29 | fi; \ 30 | done 31 | 32 | .PHONY: examples 33 | examples: 34 | for dir in examples/*; do \ 35 | if [ -f "$$dir/Makefile" ] ; then \ 36 | echo "$$dir: make this"; \ 37 | $(MAKE) -C "$$dir" this ; \ 38 | fi ; \ 39 | done 40 | 41 | .PHONY: clean 42 | clean: # mvn clean 43 | /bin/rm -rf tmp/* target/* examples/*/target/* examples/*/tmp/* 44 | /bin/rm -rf kiss.jar kiss.jar.sha256 kiss-with-tests.jar kiss-with-tests.jar.sha256 45 | /bin/rm -rf $$(find . -name '*~' -o -name '._*' -o -name '#*') 46 | 47 | tt: 48 | echo $$GPG_TTY 49 | deploy: clean all 50 | git add -f kiss.jar kiss.jar.sha256 \ 51 | kiss-with-tests.jar kiss-with-tests.jar.sha256 52 | git commit --allow-empty -m "deploy `date -u`" 53 | git push 54 | mvn clean 55 | mvn compile 56 | mvn package 57 | mvn deploy 58 | 59 | .PHONY: test 60 | test: self-test example-tests 61 | 62 | .PHONY: self-test 63 | self-test: 64 | java -cp kiss-with-tests.jar kiss.API --app kiss.util.Test 65 | 66 | .PHONY: example-tests 67 | example-tests: 68 | for dir in examples/*; do \ 69 | if [ -f "$$dir/Makefile" ] ; then \ 70 | echo "$$dir: make test"; \ 71 | $(MAKE) -C "$$dir" test ; \ 72 | fi ; \ 73 | done 74 | 75 | .PHONY: example-runs 76 | example-runs: 77 | for dir in examples/*; do \ 78 | if [ -f "$$dir/Makefile" ] ; then \ 79 | echo "$$dir: make run"; \ 80 | $(MAKE) -C "$$dir" run ; \ 81 | fi ; \ 82 | done 83 | 84 | -------------------------------------------------------------------------------- /katas/hi/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | kiss.katas 5 | hi 6 | 1.0-SNAPSHOT 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | kiss-mvn-repo 17 | https://raw.github.com/wmacevoy/kiss/mvn-repo/ 18 | 19 | true 20 | always 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | kiss 29 | kiss 30 | 1.0-SNAPSHOT 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-jar-plugin 39 | 40 | 41 | 42 | true 43 | kiss.util.Run 44 | 45 | 46 | 47 | 48 | 49 | org.codehaus.mojo 50 | exec-maven-plugin 51 | 1.5.0 52 | 53 | 54 | 55 | exec 56 | 57 | 58 | 59 | 60 | java 61 | 62 | -cp 63 | 64 | -ea 65 | kiss.util.Run 66 | --app 67 | App 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /katas/bowl/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | kiss.katas 5 | bowl 6 | 1.0-SNAPSHOT 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | kiss-mvn-repo 17 | https://raw.github.com/wmacevoy/kiss/mvn-repo/ 18 | 19 | true 20 | always 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | kiss 29 | kiss 30 | 1.0-SNAPSHOT 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-jar-plugin 39 | 40 | 41 | 42 | true 43 | kiss.util.Run 44 | 45 | 46 | 47 | 48 | 49 | org.codehaus.mojo 50 | exec-maven-plugin 51 | 1.5.0 52 | 53 | 54 | 55 | exec 56 | 57 | 58 | 59 | 60 | java 61 | 62 | -cp 63 | 64 | -ea 65 | kiss.util.Run 66 | --app 67 | App 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /katas/bus/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | kiss.katas 5 | lunch 6 | 1.0-SNAPSHOT 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | kiss-mvn-repo 17 | https://raw.github.com/wmacevoy/kiss/mvn-repo/ 18 | 19 | true 20 | always 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | kiss 29 | kiss 30 | 1.0-SNAPSHOT 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-jar-plugin 39 | 40 | 41 | 42 | true 43 | kiss.util.Run 44 | 45 | 46 | 47 | 48 | 49 | org.codehaus.mojo 50 | exec-maven-plugin 51 | 1.5.0 52 | 53 | 54 | 55 | exec 56 | 57 | 58 | 59 | 60 | java 61 | 62 | -cp 63 | 64 | -ea 65 | kiss.util.Run 66 | --app 67 | App 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /katas/branches/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | kiss.katas 5 | branches 6 | 1.0-SNAPSHOT 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | kiss-mvn-repo 17 | https://raw.github.com/wmacevoy/kiss/mvn-repo/ 18 | 19 | true 20 | always 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | kiss 29 | kiss 30 | 1.0-SNAPSHOT 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-jar-plugin 39 | 40 | 41 | 42 | true 43 | kiss.util.Run 44 | 45 | 46 | 47 | 48 | 49 | org.codehaus.mojo 50 | exec-maven-plugin 51 | 1.5.0 52 | 53 | 54 | 55 | exec 56 | 57 | 58 | 59 | 60 | java 61 | 62 | -cp 63 | 64 | -ea 65 | kiss.util.Run 66 | --app 67 | App 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /katas/methods/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | kiss.katas 5 | methods 6 | 1.0-SNAPSHOT 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | kiss-mvn-repo 17 | https://raw.github.com/wmacevoy/kiss/mvn-repo/ 18 | 19 | true 20 | always 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | kiss 29 | kiss 30 | 1.0-SNAPSHOT 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-jar-plugin 39 | 40 | 41 | 42 | true 43 | kiss.util.Run 44 | 45 | 46 | 47 | 48 | 49 | org.codehaus.mojo 50 | exec-maven-plugin 51 | 1.5.0 52 | 53 | 54 | 55 | exec 56 | 57 | 58 | 59 | 60 | java 61 | 62 | -cp 63 | 64 | -ea 65 | kiss.util.Run 66 | --app 67 | App 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/TestIO.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import static kiss.API.*; 4 | 5 | import java.io.PrintStream; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | 9 | class TestIO { 10 | void testOutExpect() { 11 | outExpect(1, 2, 3, EOL, 12 | "testing", EOL, 13 | "ok", EOL, 14 | 1.0, 2.0, 3.0, EOL, 15 | "alpha", "beta", "tango"); 16 | println(1, 2, 3); 17 | println("testing"); 18 | println("ok"); 19 | println(1.0, 2.0, 3.0); 20 | println("alpha", "beta", "tango"); 21 | outClose(); 22 | 23 | } 24 | 25 | void testInProvide() { 26 | inProvide(1, 2, 3, EOL, 27 | "testing", EOL, 28 | "ok", EOL, 29 | 1.5, 2.0, 3.0, EOL, 30 | "alpha", "beta", "tango"); 31 | 32 | assert readInt() == 1; 33 | assert readInt() == 2; 34 | assert readInt() == 3; 35 | assert readEOL().equals(EOL); 36 | assert readLine().equals("testing"); 37 | assert readLine().equals("ok"); 38 | 39 | assert readDouble() == 1.5; 40 | assert readDouble() == 2.0; 41 | assert readDouble() == 3.0; 42 | assert readEOL().equals(EOL); 43 | 44 | inClose(); 45 | } 46 | 47 | void testVerify() { 48 | boolean skip = false; 49 | try { // use java.io stuff to confidently create file content 50 | try (PrintStream ps 51 | = new PrintStream(new FileOutputStream("test.txt"))) { 52 | 53 | ps.println("Testing 1 2 3..."); 54 | ps.println(1); 55 | ps.println(PI); 56 | } 57 | } catch (IOException e) { 58 | print("failed file i/o --- maybe android? Error: " + e); 59 | print("skipping this test"); 60 | return; 61 | } 62 | 63 | 64 | // verify with the kiss approach 65 | try (Close vfy = outVerify("test.txt")) { 66 | println("Testing 1 2 3..."); 67 | println(1); 68 | println(PI); 69 | } 70 | 71 | // verify that it also catches errors: 72 | boolean caught = false; 73 | try { 74 | try (Close vfy = outVerify("test.txt")) { 75 | println("Testing 1 2 3..."); 76 | println(2); 77 | println(PI); 78 | } 79 | } catch (kiss.util.VerifyRuntimeException ae) { 80 | caught = true; 81 | } 82 | assert caught == true; 83 | } 84 | 85 | void testPrintf() { 86 | try (Close out = outExpect("Hello, World!", EOL)) { 87 | printf("Hello, %s!\n", "World"); 88 | } 89 | try (Close out = outExpect("3.14", EOL)) { 90 | printf("%1.2f\n", PI); 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /examples/helloworld/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss-examples-helloworld 6 | 1-SNAPSHOT 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.github.wmacevoy 17 | kiss 18 | LATEST 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-javadoc-plugin 27 | 2.10.4 28 | 29 | -Xdoclint:none 30 | private 31 | true 32 | 33 | 34 | 35 | attach-javadocs 36 | 37 | jar 38 | 39 | 40 | 41 | 42 | 43 | 44 | org.apache.maven.plugins 45 | maven-jar-plugin 46 | 3.0.2 47 | 48 | 49 | jar-with-dependencies 50 | 51 | 52 | 53 | true 54 | kiss.API 55 | 56 | 57 | 58 | 59 | 60 | org.codehaus.mojo 61 | exec-maven-plugin 62 | 1.5.0 63 | 64 | 65 | 66 | exec 67 | 68 | 69 | 70 | 71 | java 72 | 73 | -cp 74 | 75 | -ea 76 | kiss.API 77 | --app 78 | App 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/VerifyOutputStream.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | 7 | public class VerifyOutputStream extends OutputStream { 8 | private String code(int ch) { 9 | if (ch == -1) return "END"; 10 | ch = ch & 0xFFFF; 11 | if (ch == '\t') return "TAB (code 9)"; 12 | if (ch == '\n') return "LF (code 10)"; 13 | if (ch == '\r') return "CR (code 13)"; 14 | if (ch < 32) return 15 | "'\\u" + 16 | String.format("%040x",ch) + 17 | "' (code " + ((int) ch) + ")"; 18 | return "'" + ((char) ch) + "' (code " + ((int) ch) + ")"; 19 | } 20 | 21 | InputStream verify; 22 | long at = 0L; 23 | long mismatch = Long.MAX_VALUE; 24 | 25 | public boolean matches() { return mismatch == Long.MAX_VALUE; } 26 | public long getMismatch() { return mismatch; } 27 | 28 | public VerifyOutputStream(InputStream _verify) { 29 | verify = _verify; 30 | } 31 | 32 | public void flush() throws IOException { 33 | }; 34 | 35 | public void write(byte[] data, int offset, int length) throws IOException { 36 | if (offset != 0 || length != data.length) { 37 | byte[] writedata = new byte[length]; 38 | System.arraycopy(data, offset, writedata, 0, length); 39 | write(writedata); 40 | } else { 41 | write(data); 42 | } 43 | } 44 | 45 | public void write(byte[] data) throws IOException { 46 | byte[] rdata = new byte[data.length]; 47 | if (mismatch == Long.MAX_VALUE) { 48 | long readBytes = verify.read(rdata); 49 | if ((readBytes == data.length) && java.util.Arrays.equals(data, rdata)) { 50 | at += readBytes; 51 | return; 52 | } 53 | int i = 0; 54 | for (i = 0; i < readBytes; ++i) { 55 | if (data[i] != rdata[i]) 56 | break; 57 | } 58 | mismatch = at + i; 59 | verify.close(); 60 | throw 61 | new VerifyRuntimeException 62 | ("Mismatch at byte offset " + mismatch + "." + 63 | " Expected " + code(rdata[i]) + 64 | " but got " + code(data[i])); 65 | } 66 | } 67 | 68 | public void write(int b) throws IOException { 69 | byte[] data = new byte[1]; 70 | data[0] = (byte) b; 71 | write(data); 72 | } 73 | 74 | public void close() throws IOException { 75 | if (mismatch == Long.MAX_VALUE) { 76 | int ch = verify.read(); 77 | if (ch != -1) { 78 | mismatch = at; 79 | throw 80 | new VerifyRuntimeException 81 | ("Mismatch at byte offset " + mismatch + "." + 82 | " Expected " + code(ch) + 83 | " but got " + code(-1)); 84 | } 85 | } 86 | verify.close(); 87 | if (!matches()) { 88 | throw new VerifyRuntimeException("Mismatch at byte offset " + mismatch); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /katas/bus/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | // the fixed price of a bus ride 5 | public static final double PRICE = 1.25; 6 | 7 | // money in your pocket 8 | double money; 9 | 10 | // passes you have 11 | double passes; 12 | 13 | 14 | void testCanRideKata1() { 15 | money = 0.75; 16 | passes = 0; 17 | assert canRide() == false; 18 | 19 | money = 10.00; 20 | passes = 2; 21 | assert canRide() == true; 22 | } 23 | 24 | void testCanRideKata2() { 25 | money = 10.00; 26 | passes = 0; 27 | assert canRide() == true; 28 | 29 | money = 0.05; 30 | passes = 2; 31 | assert canRide() == true; 32 | } 33 | 34 | void testCanRideKata3() { 35 | money = PRICE; 36 | passes = 0; 37 | assert canRide() == true; 38 | 39 | money = PRICE-0.01; 40 | passes = 1; 41 | assert canRide() == true; 42 | 43 | money = PRICE-0.01; 44 | passes = 0; 45 | assert canRide() == false; 46 | } 47 | 48 | void testRideKata1() { 49 | money = 0.75; 50 | passes = 0; 51 | if (canRide()) { ride(); } 52 | assert money == 0.75; 53 | assert passes == 0; 54 | 55 | money = 10.00; 56 | passes = 2; 57 | if (canRide()) { ride(); } 58 | assert money == 10.00; 59 | assert passes == 1; 60 | } 61 | 62 | void testRideKata2() { 63 | money = 10.00; 64 | passes = 0; 65 | if (canRide()) { ride(); } 66 | assert money == 10.00-PRICE; 67 | assert passes == 0; 68 | 69 | money = 0.05; 70 | passes = 2; 71 | if (canRide()) { ride(); } 72 | assert money == 0.05; 73 | assert passes == 1; 74 | } 75 | 76 | void testRideKata3() { 77 | money = PRICE; 78 | passes = 0; 79 | if (canRide()) { ride(); } 80 | assert money == 0; 81 | assert passes == 0; 82 | 83 | money = PRICE-0.01; 84 | passes = 1; 85 | if (canRide()) { ride(); } 86 | assert money == PRICE-0.01; 87 | assert passes == 0; 88 | 89 | money = PRICE-0.01; 90 | passes = 0; 91 | if (canRide()) { ride(); } 92 | assert money == PRICE-0.01; 93 | assert passes == 0; 94 | } 95 | 96 | void testRideNinja() { 97 | boolean caught = false; 98 | 99 | money = PRICE-0.01; 100 | passes = 0; 101 | try { 102 | ride(); 103 | } catch (Error e) { 104 | caught = e.getMessage().equals("get off the bus!"); 105 | } 106 | assert caught == true; 107 | assert money == PRICE-0.01; 108 | assert passes == 0; 109 | } 110 | 111 | boolean canRide() { 112 | // canRide should be true if either 113 | // you have enough money (PRICE) 114 | // or have at least one pass 115 | 116 | // TODO 117 | return false; 118 | } 119 | 120 | void ride() { 121 | // ride should use a pass if possible 122 | // otherwise it should use money. 123 | 124 | // TODO 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/TestCipher.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import static kiss.API.*; 4 | 5 | class TestCipher { 6 | void testHex() { 7 | assert Cipher.hex(null) == null; 8 | assert Cipher.hex(new byte[] { }).equals(""); 9 | assert Cipher.hex(new byte[] { (byte) 0x00 }).equals("00"); 10 | assert Cipher.hex(new byte[] { (byte) 0x09 }).equals("09"); 11 | assert Cipher.hex(new byte[] { (byte) 0x0a }).equals("0a"); 12 | assert Cipher.hex(new byte[] { (byte) 0x0f }).equals("0f"); 13 | assert Cipher.hex(new byte[] { (byte) 0x90 }).equals("90"); 14 | assert Cipher.hex(new byte[] { (byte) 0x99 }).equals("99"); 15 | assert Cipher.hex(new byte[] { (byte) 0x9a }).equals("9a"); 16 | assert Cipher.hex(new byte[] { (byte) 0x9f }).equals("9f"); 17 | assert Cipher.hex(new byte[] { (byte) 0xa0 }).equals("a0"); 18 | assert Cipher.hex(new byte[] { (byte) 0xa9 }).equals("a9"); 19 | assert Cipher.hex(new byte[] { (byte) 0xaa }).equals("aa"); 20 | assert Cipher.hex(new byte[] { (byte) 0xaf }).equals("af"); 21 | assert Cipher.hex(new byte[] { (byte) 0xf0 }).equals("f0"); 22 | assert Cipher.hex(new byte[] { (byte) 0xf9 }).equals("f9"); 23 | assert Cipher.hex(new byte[] { (byte) 0xfa }).equals("fa"); 24 | assert Cipher.hex(new byte[] { (byte) 0xff }).equals("ff"); 25 | 26 | assert Cipher.hex(new byte[] { (byte) 0xde, 27 | (byte) 0xad, 28 | (byte) 0xbe, 29 | (byte) 0xef }).equals("deadbeef"); 30 | 31 | } 32 | 33 | void testBin() { 34 | assert Cipher.bin(null) == null; 35 | assert asString(Cipher.bin("")).equals("[]"); 36 | assert asString(Cipher.bin("807f00")).equals("[-128, 127, 0]"); 37 | assert asString(Cipher.bin("80_7f_00 ")).equals("[-128, 127, 0]"); 38 | assert asString(Cipher.bin("a")).equals("[10]"); 39 | assert asString(Cipher.bin("7fa")).equals("[127, 10]"); 40 | } 41 | 42 | void testSha256() { 43 | assert Cipher.sha256("").equals("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); 44 | assert Cipher.sha256("a").equals("ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"); 45 | assert Cipher.sha256("x").equals("2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"); 46 | } 47 | 48 | void testEncrypt() { 49 | String[] keys = new String[] { "", "a", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 50 | "b", "ab", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" }; 51 | 52 | String[] plains = new String[] { "", "x", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 53 | "y", "xy", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy" }; 54 | 55 | // never encrypts twice to same cipher 56 | for (String key : keys) { 57 | for (String plain : plains) { 58 | assert !Cipher.encrypt(key,plain).equals(Cipher.encrypt(key,plain)); 59 | } 60 | } 61 | 62 | // right key works 63 | for (String key : keys) { 64 | for (String plain : plains) { 65 | assert Cipher.decrypt(key,Cipher.encrypt(key,plain)).equals(plain); 66 | } 67 | } 68 | 69 | // wrong key fails 70 | for (String key1 : keys) { 71 | for (String key2 : keys) { 72 | if (!key1.equals(key2)) { 73 | for (String plain : plains) { 74 | assert Cipher.decrypt(key1,Cipher.encrypt(key2,plain)) == null; 75 | } 76 | } 77 | } 78 | } 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /katas/branches/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | 5 | boolean isWeekend; 6 | boolean isSunny; 7 | 8 | void ifSunny() { 9 | // TODO: println the message "sunny!" if isSunny is true 10 | } 11 | 12 | 13 | void ifSunnyElseCold() { 14 | // TODO: println the message "sunny!" if isSunny is true, 15 | // println the message "cold." if isSunny is false 16 | } 17 | 18 | void ifSunnyAndWeekend() { 19 | // TODO: print the message "going out!" if both sunny and weekend are 20 | // true. Otherwise print nothing. 21 | } 22 | 23 | void ifPlans() { 24 | // TODO: print the message "going out!" if both sunny and weekend 25 | // are true. If is isn't sunny, but is the weekend, 26 | // print out the message "hanging out with friends". If 27 | // none of these are true, then, print out "waiting for the 28 | // weekend" 29 | // You should be able to do this with 3 println statements 30 | // 31 | } 32 | 33 | void testIfSunny() { 34 | String [] expects = new String[] { null, "sunny!", null, "sunny!" }; 35 | for (int p=0; p<2; ++p) { 36 | for (int q=0; q<2; ++q) { 37 | isWeekend = asBoolean(p); 38 | isSunny = asBoolean(q); 39 | String expect = expects[2*p+q]; 40 | if (expect != null) { 41 | try (Close out = outExpect(expect)) { ifSunny(); } 42 | } else { 43 | try (Close out = outExpect()) { ifSunny(); } 44 | } 45 | } 46 | } 47 | } 48 | 49 | void testIfSunnyElseCold() { 50 | String [] expects = new String[] { 51 | "cold.", "sunny!", "cold.", "sunny!" 52 | }; 53 | for (int p=0; p<2; ++p) { 54 | for (int q=0; q<2; ++q) { 55 | isWeekend = asBoolean(p); 56 | isSunny = asBoolean(q); 57 | String expect = expects[2*p+q]; 58 | if (expect != null) { 59 | try (Close out = outExpect(expect)) { ifSunnyElseCold(); } 60 | } else { 61 | try (Close out = outExpect()) { ifSunnyElseCold(); } 62 | } 63 | } 64 | } 65 | } 66 | 67 | void testIfSunnyAndWeekend() { 68 | String [] expects = new String[] { 69 | null, null, null, "going out!" 70 | }; 71 | for (int p=0; p<2; ++p) { 72 | for (int q=0; q<2; ++q) { 73 | isWeekend = asBoolean(p); 74 | isSunny = asBoolean(q); 75 | String expect = expects[2*p+q]; 76 | if (expect != null) { 77 | try (Close out = outExpect(expect)) { 78 | ifSunnyAndWeekend(); 79 | } 80 | } else { 81 | try (Close out = outExpect()) { 82 | ifSunnyAndWeekend(); 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | void testIfPlans() { 90 | String [] expects = new String[] { 91 | "waiting for the weekend", "waiting for the weekend", 92 | "hanging out with friends", "going out!" 93 | }; 94 | for (int p=0; p<2; ++p) { 95 | for (int q=0; q<2; ++q) { 96 | isWeekend = asBoolean(p); 97 | isSunny = asBoolean(q); 98 | if (expect != null) { 99 | try (Close out = outExpect(expect)) { 100 | ifPlans(); 101 | } 102 | } else { 103 | try (Close out = outExpect()) { 104 | ifPlans(); 105 | } 106 | } 107 | } 108 | } 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/TestAs.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import static kiss.API.*; 4 | 5 | class TestAs { 6 | void testAsBoolean() { 7 | assert As.asBoolean(true) == true; 8 | assert As.asBoolean(false) == false; 9 | assert As.asBoolean('\u0000') == false; 10 | assert As.asBoolean('\u1234') == true; 11 | assert As.asBoolean((String) null) == false; 12 | assert As.asBoolean("") == false; 13 | assert As.asBoolean("false") == false; 14 | assert As.asBoolean("anything else") == true; 15 | assert As.asBoolean(((short) 0)) == false; 16 | assert As.asBoolean(((short) 22)) == true; 17 | assert As.asBoolean(((int) 0)) == false; 18 | assert As.asBoolean(((int) 22)) == true; 19 | assert As.asBoolean(((long) 0)) == false; 20 | assert As.asBoolean(((long) 22)) == true; 21 | assert As.asBoolean(((float) 0)) == false; 22 | assert As.asBoolean(((float) 22)) == true; 23 | assert As.asBoolean(((double) 0)) == false; 24 | assert As.asBoolean(((double) 22)) == true; 25 | 26 | assert As.asBoolean(new Boolean(false)) == false; 27 | assert As.asBoolean(new Boolean(true)) == true; 28 | assert As.asBoolean("") == false; 29 | assert As.asBoolean("false") == false; 30 | assert As.asBoolean("unlikely") == true; 31 | assert As.asBoolean(new Long(0x1_00000000L)) == true; 32 | assert As.asBoolean(new Long(0)) == false; 33 | assert As.asBoolean(new Double(Double.MIN_VALUE)) == true; 34 | assert As.asBoolean(new Double(Double.MAX_VALUE)) == true; 35 | assert As.asBoolean(new Double(0)) == false; 36 | 37 | assert As.asBoolean((Object) new Boolean(false)) == false; 38 | assert As.asBoolean((Object) new Boolean(true)) == true; 39 | assert As.asBoolean((Object) "") == false; 40 | assert As.asBoolean((Object) "false") == false; 41 | assert As.asBoolean((Object) "unlikely") == true; 42 | assert As.asBoolean((Object) new Long(0x1_00000000L)) == true; 43 | assert As.asBoolean((Object) new Long(0)) == false; 44 | assert As.asBoolean((Object) new Double(Double.MIN_VALUE)) == true; 45 | assert As.asBoolean((Object) new Double(Double.MAX_VALUE)) == true; 46 | assert As.asBoolean((Object) new Double(0)) == false; 47 | } 48 | 49 | void testAsChar() { 50 | assert As.asChar(false) == '\u0000'; 51 | assert As.asChar(true) == '\u0001'; 52 | assert As.asChar("words") == 'w'; 53 | assert As.asChar("") == '\u0000'; 54 | assert As.asChar((String) null) == '\u0000'; 55 | assert As.asChar(PI) == (char) PI; 56 | 57 | assert As.asChar(new Boolean(true)) == '\u0001'; 58 | assert As.asChar(new Boolean(false)) == '\u0000'; 59 | assert As.asChar(new Integer('a'+2)) == 'c'; 60 | assert As.asChar(new Character((char)('a'+2))) == 'c'; 61 | 62 | assert As.asChar((Object)new Boolean(true)) == '\u0001'; 63 | assert As.asChar((Object)new Boolean(false)) == '\u0000'; 64 | assert As.asChar((Object)new Integer('a'+2)) == 'c'; 65 | assert As.asChar((Object)new Character((char)('a'+2))) == 'c'; 66 | } 67 | 68 | void testAsShort() { 69 | assert As.asShort(false) == 0; 70 | assert As.asShort(true) == 1; 71 | println(As.asShort("10")); 72 | assert As.asShort("10") == 10; 73 | assert As.asShort("0x10") == 16; 74 | assert As.asShort("0b10") == 2; 75 | assert As.asShort("12_345") == 12_345; 76 | assert As.asShort(PI) == (short) PI; 77 | } 78 | 79 | void testAsInt() { 80 | assert As.asInt(false) == 0; 81 | assert As.asInt(true) == 1; 82 | assert As.asInt("42") == 42; 83 | assert As.asInt("0x80") == 128; 84 | assert As.asInt("0b1000_0000") == 128; 85 | assert As.asInt(new Double(PI)) == 3; 86 | assert As.asInt((Object) new Double(PI)) == 3; 87 | } 88 | 89 | void testAsDouble() { 90 | assert As.asDouble("1_234.456_789") == 1_234.456_789; 91 | } 92 | 93 | void testAsString() { 94 | assert As.asString(false).equals("false"); 95 | assert As.asString(true).equals("true"); 96 | assert As.asString(0xFF).equals("255"); 97 | } 98 | 99 | void testREADME() { 100 | assert asDouble(3)/asDouble(2) == 1.5; 101 | assert asInt("0xff_ff") == 0xff_ff; 102 | assert asString('a').equals("a"); 103 | assert asChar("a") == 'a'; 104 | assert asBoolean(0) == false; 105 | assert asBoolean(1) == true; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /examples/prime/src/main/java/App.java: -------------------------------------------------------------------------------- 1 | import static kiss.API.*; 2 | 3 | class App { 4 | 5 | boolean skipSlowTests = true; 6 | 7 | void testIsPrimeSmallTrueCases() { 8 | assert isPrime( 2) == true; 9 | assert isPrime( 3) == true; 10 | assert isPrime( 5) == true; 11 | assert isPrime( 7) == true; 12 | } 13 | void testIsPrimeSmallFalseCases() { 14 | assert isPrime(-5) == false; 15 | assert isPrime(-4) == false; 16 | assert isPrime(-3) == false; 17 | assert isPrime(-2) == false; 18 | assert isPrime(-1) == false; 19 | assert isPrime( 0) == false; 20 | assert isPrime( 1) == false; 21 | assert isPrime( 4) == false; 22 | assert isPrime( 6) == false; 23 | assert isPrime( 8) == false; 24 | assert isPrime( 9) == false; 25 | assert isPrime(10) == false; 26 | } 27 | 28 | void testIsPrimeRandomNegativeCases() { 29 | for (int i=0; i<100; ++i) { 30 | assert isPrime(random(Integer.MIN_VALUE,-1)) == false; 31 | } 32 | } 33 | 34 | void testIsPrimeRandomCompositeCases() { 35 | // make sure integer math does not overflow 36 | int n=(int) floor(sqrt(Integer.MAX_VALUE)); 37 | for (int i=0; i<100; ++i) { 38 | assert isPrime(random(2,n)*random(2,n)) == false; 39 | } 40 | } 41 | 42 | void testIsPrimeLargeCases() { 43 | // http://compoasso.free.fr/primelistweb/page/prime/liste_online_en.php 44 | assert isPrime( 11) == true; 45 | assert isPrime( 101) == true; 46 | assert isPrime( 1009) == true; 47 | assert isPrime( 10007) == true; 48 | assert isPrime( 100003) == true; 49 | assert isPrime( 1000003) == true; 50 | assert isPrime( 10000019) == true; 51 | assert isPrime( 100000007) == true; 52 | assert isPrime(1000000007) == true; 53 | } 54 | 55 | void testIsPrimeSame() { 56 | if (skipSlowTests) { 57 | println("skipSlowTests"); 58 | return; 59 | } 60 | for (int i=0; i<100; ++i) { 61 | int n = random(Integer.MIN_VALUE,Integer.MAX_VALUE); 62 | assert isPrimeSlow(n) == isPrime(n); 63 | } 64 | } 65 | 66 | void testIsPrimeFast() { 67 | if (skipSlowTests) { 68 | println("skipSlowTests"); 69 | return; 70 | } 71 | 72 | int tests = 100; 73 | double init = 1; 74 | int minVal = 1_000_000_000; 75 | int maxVal = 1_999_999_999; 76 | double t0; 77 | 78 | seed(init); 79 | t0 = time(); 80 | boolean tmp = false; 81 | for (int i = 0; i < tests; ++i) { 82 | int n = random(minVal,maxVal); 83 | if (isPrimeSlow(n)) { tmp = !tmp; } 84 | } 85 | double slowTime=time()-t0; 86 | 87 | seed(init); 88 | t0 = time(); 89 | for (int i = 0; i < tests; ++i) { 90 | int n = random(minVal,maxVal); 91 | if (isPrime(n)) { tmp = !tmp; } 92 | } 93 | double fastTime=time()-t0; 94 | 95 | println("speedup: " + round(slowTime/fastTime) + " junk: " + tmp); 96 | 97 | assert fastTime < 0.1*slowTime; 98 | } 99 | 100 | boolean isPrimeSlow(int x) { 101 | if (x > 1) { 102 | for (int i=2; i 1) { 112 | if (x == 2) return true; 113 | if (x % 2 == 0) return false; 114 | int i=3; 115 | while (i*i <= x) { 116 | if (x % i == 0) return false; 117 | i = i + 2; 118 | } 119 | return true; 120 | } else { 121 | return false; 122 | } 123 | } 124 | 125 | public void run() 126 | { 127 | for (;;) { 128 | print("Number to check (0 to exit)? "); 129 | int n = readInteger(); 130 | if (n == 0) break; 131 | if (isPrime(n)) { 132 | println(n + " is prime."); 133 | } else { 134 | println(n + " is not prime."); 135 | } 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.github.wmacevoy 5 | kiss 6 | jar 7 | 1.2 8 | ${project.groupId}:${project.artifactId} 9 | 10 | Learing and teaching programming concepts with Java kept simple. 11 | 12 | 13 | 14 | Warren MacEvoy 15 | wmacevoy@gmail.com 16 | Colorado Mesa University 17 | http://www.coloradomesa.edu 18 | 19 | 20 | 21 | scm:git:git://github.com/wmacevoy/kiss.git 22 | scm:git:ssh://github.com:wmacevoy/kiss.git 23 | http://github.com/wmacevoy/kiss/tree/master 24 | 25 | 26 | 27 | The Apache License, Version 2.0 28 | http://www.apache.org/licenses/LICENSE-2.0.txt 29 | 30 | 31 | 32 | https://github.com/wmacevoy/kiss 33 | 34 | UTF-8 35 | github 36 | 37 | 38 | 39 | ossrh 40 | https://oss.sonatype.org/content/repositories/snapshots 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.sonatype.plugins 49 | nexus-staging-maven-plugin 50 | 1.6.7 51 | true 52 | 53 | ossrh 54 | https://oss.sonatype.org/ 55 | true 56 | 57 | 58 | 59 | 60 | org.apache.maven.plugins 61 | maven-compiler-plugin 62 | 3.5.1 63 | 64 | 1.8 65 | 1.8 66 | 67 | 68 | 69 | org.codehaus.mojo 70 | exec-maven-plugin 71 | 1.5.0 72 | 73 | 74 | 75 | exec 76 | 77 | 78 | 79 | 80 | java 81 | 82 | -cp 83 | 84 | -ea 85 | kiss.util.Run 86 | --app 87 | kiss.util.Test 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-source-plugin 94 | 2.2.1 95 | 96 | 97 | attach-sources 98 | 99 | jar-no-fork 100 | 101 | 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-javadoc-plugin 107 | 108 | -Xdoclint:none 109 | 110 | 111 | 112 | attach-javadocs 113 | 114 | jar 115 | 116 | 117 | 118 | 119 | 120 | org.apache.maven.plugins 121 | maven-gpg-plugin 122 | 1.5 123 | 124 | 125 | sign-artifacts 126 | verify 127 | 128 | sign 129 | 130 | 131 | 132 | --pinentry-mode 133 | loopback 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | junit 144 | junit 145 | 3.8.1 146 | test 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/TestRun.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import static kiss.API.*; 4 | 5 | public class TestRun { 6 | public static void main(String [] args) { 7 | test(new TestRun()); 8 | } 9 | void testTime() { 10 | double s=java.lang.System.currentTimeMillis()/1000.0; 11 | double t=time(); 12 | assert abs(s-t)<0.01; 13 | } 14 | 15 | void testPause() { 16 | double dt = 0.1; 17 | double t0=time(); 18 | pause(dt); 19 | double t=time()-t0; 20 | assert t >= dt; 21 | } 22 | 23 | void testMain() throws Exception { 24 | // save globals to restore after test 25 | String[] _APP_ARGS = kiss.API.APP_ARGS; 26 | String _APP_NAME = kiss.API.APP_NAME; 27 | Object _APP = kiss.API.APP; 28 | boolean appWasTested = Run.testedAlready.contains(TestApp.class); 29 | 30 | kiss.API.APP_NAME=null; 31 | kiss.API.APP_ARGS=null; 32 | kiss.API.APP=null; 33 | 34 | Run.testedAlready.remove(TestApp.class); 35 | Run.main(new String[] { "--app", "kiss.util.TestApp","a","b","c" }); 36 | 37 | assert kiss.API.APP_NAME.equals("kiss.util.TestApp"); 38 | assert java.util.Arrays.equals(kiss.API.APP_ARGS, 39 | new String[] { "a","b","c" }); 40 | assert kiss.API.APP instanceof TestApp; 41 | { 42 | TestApp app = (TestApp) APP; 43 | assert app.constructed == 1; 44 | assert app.tested == 1; 45 | assert app.ran == 1; 46 | assert app.closed == 1; 47 | } 48 | 49 | kiss.API.APP_NAME=null; 50 | kiss.API.APP_ARGS=null; 51 | kiss.API.APP=null; 52 | 53 | Run.testedAlready.remove(TestApp.class); 54 | Run.main(new String[] { "--notest","--app", "kiss.util.TestApp","a","b","c" }); 55 | 56 | assert kiss.API.APP_NAME.equals("kiss.util.TestApp"); 57 | assert java.util.Arrays.equals(kiss.API.APP_ARGS, 58 | new String[] { "a","b","c" }); 59 | assert kiss.API.APP instanceof TestApp; 60 | { 61 | TestApp app = (TestApp) APP; 62 | assert app.constructed == 1; 63 | assert app.tested == 0; 64 | assert app.ran == 1; 65 | assert app.closed == 1; 66 | } 67 | 68 | kiss.API.APP_NAME=null; 69 | kiss.API.APP_ARGS=null; 70 | kiss.API.APP=null; 71 | Run.testedAlready.remove(TestApp.class); 72 | Run.main(new String[] { "--norun","--app", "kiss.util.TestApp","a","b","c" }); 73 | assert kiss.API.APP_NAME.equals("kiss.util.TestApp"); 74 | assert java.util.Arrays.equals(kiss.API.APP_ARGS, 75 | new String[] { "a","b","c" }); 76 | assert kiss.API.APP instanceof TestApp; 77 | { 78 | TestApp app = (TestApp) APP; 79 | assert app.constructed == 1; 80 | assert app.tested == 1; 81 | assert app.ran == 0; 82 | assert app.closed == 1; 83 | } 84 | 85 | // restore globals 86 | kiss.API.APP_ARGS = _APP_ARGS; 87 | kiss.API.APP_NAME = _APP_NAME; 88 | kiss.API.APP = _APP; 89 | 90 | if (appWasTested) { 91 | Run.testedAlready.add(TestApp.class); 92 | } else { 93 | Run.testedAlready.remove(TestApp.class); 94 | } 95 | 96 | } 97 | 98 | void testTest() { 99 | boolean appWasTested = Run.testedAlready.contains(TestApp.class); 100 | Run.testedAlready.remove(TestApp.class); 101 | TestApp app = new TestApp(); 102 | assert app.constructed == 1; 103 | test(app); 104 | assert app.constructed == 1; 105 | assert app.tested == 1; 106 | assert app.ran == 0; 107 | assert app.closed == 0; 108 | 109 | test(app); 110 | assert app.constructed == 1; 111 | assert app.tested == 1; 112 | assert app.ran == 0; 113 | assert app.closed == 0; 114 | 115 | testAlways(app); 116 | assert app.constructed == 1; 117 | assert app.tested == 2; 118 | assert app.ran == 0; 119 | assert app.closed == 0; 120 | 121 | if (appWasTested) { 122 | Run.testedAlready.add(TestApp.class); 123 | } else { 124 | Run.testedAlready.remove(TestApp.class); 125 | } 126 | } 127 | 128 | class Sample1 { 129 | java.util.ArrayList order 130 | = new java.util.ArrayList(); 131 | 132 | void testA() { 133 | order.add("a"); 134 | } 135 | void testX() { 136 | order.add("b"); 137 | } 138 | void testQ() { 139 | order.add("c"); 140 | } 141 | } 142 | 143 | class Sample2 { 144 | java.util.ArrayList order 145 | = new java.util.ArrayList(); 146 | 147 | void testC() { 148 | order.add("a"); 149 | } 150 | void testB() { 151 | order.add("b"); 152 | } 153 | void testAAA() { 154 | order.add("c"); 155 | } 156 | } 157 | 158 | class Sample3 { 159 | java.util.ArrayList order 160 | = new java.util.ArrayList(); 161 | 162 | protected void testCxkdmY() { 163 | order.add("a"); 164 | } 165 | 166 | void some() { } 167 | void test12444() { 168 | order.add("b"); 169 | } 170 | 171 | void other() {} 172 | private void testUUAAA() { 173 | order.add("c"); 174 | } 175 | 176 | void stuff() {} 177 | } 178 | 179 | class Sample4 { 180 | java.util.ArrayList order 181 | = new java.util.ArrayList(); 182 | 183 | protected void testA() { 184 | order.add("a"); 185 | } 186 | 187 | void some() { } 188 | private void testAtestAtestA() { 189 | order.add("b"); 190 | } 191 | 192 | void other() {} 193 | void testAtestA() { 194 | order.add("c"); 195 | } 196 | 197 | void stuff() {} 198 | } 199 | 200 | 201 | 202 | void testOrder() { 203 | assert asString(test(new Sample1()).order).equals("[a,b,c]"); 204 | assert asString(test(new Sample2()).order).equals("[a,b,c]"); 205 | assert asString(test(new Sample3()).order).equals("[a,b,c]"); 206 | assert asString(test(new Sample4()).order).equals("[a,b,c]"); 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/Run.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import static kiss.API.*; 4 | 5 | 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Field; 9 | import java.lang.reflect.Constructor; 10 | import java.text.DecimalFormat; 11 | import java.util.Date; 12 | import java.util.HashSet; 13 | import java.util.ArrayList; 14 | import java.io.InputStream; 15 | 16 | public class Run { 17 | // modified by TestRun so not private 18 | static HashSet> testedAlready = new HashSet>(); 19 | 20 | public static final void main(String[] _args) throws Exception { 21 | 22 | ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 23 | 24 | // 0. The default app object is App (default package). You can 25 | // choose another object using the --app command line 26 | // option or the JAVA_APP environment variable. 27 | // 28 | // 1. Contruct app object. Use the String[] args constructor 29 | // if it is available. Otherwise, use the default constructor. 30 | // 31 | // 32 | // 2. Invoke testXXX() methods. For reproducability, the 33 | // random number seed is set to 1 before each test. 34 | // 35 | // 3. Call the run() method. 36 | // 37 | // 4. Call the close() method (even if a test or run fails) 38 | 39 | boolean doTest = true; 40 | boolean doRun = true; 41 | String className = "App"; // default class is "App" in default package 42 | String[] args; 43 | 44 | if (System.getenv("JAVA_APP") != null) { // env override 45 | className = System.getenv("JAVA_APP"); 46 | } 47 | 48 | int argi; 49 | for (argi=0; argi < _args.length; ++argi) { 50 | if (_args[argi].equals("--")) { 51 | ++argi; 52 | break; 53 | } 54 | 55 | if (_args[argi].equals("--norun")) { 56 | doRun = false; 57 | continue; 58 | } 59 | 60 | if (_args[argi].equals("--notest")) { 61 | doTest = false; 62 | continue; 63 | } 64 | 65 | if (_args[argi].equals("--app")) { 66 | className = _args[++argi]; 67 | continue; 68 | } 69 | 70 | break; 71 | } 72 | 73 | args = new String[_args.length - argi]; 74 | System.arraycopy(_args,argi,args,0,args.length); 75 | 76 | Class appClass = Class.forName(className); 77 | 78 | kiss.API.APP_NAME=className; 79 | kiss.API.APP_ARGS=java.util.Arrays.copyOf(args,args.length); 80 | 81 | Object app = null; 82 | 83 | try { 84 | Constructor constructor = appClass.getDeclaredConstructor(); 85 | constructor.setAccessible(true); 86 | app = constructor.newInstance(); 87 | 88 | kiss.API.APP=app; 89 | 90 | if (doTest) { 91 | test(app); 92 | } 93 | 94 | if (doRun) { 95 | try { 96 | Method run = app.getClass().getDeclaredMethod("run"); 97 | kiss.API.seed(); 98 | run.setAccessible(true); 99 | run.invoke(app); 100 | } catch (NoSuchMethodException e) {} 101 | } 102 | } finally { 103 | if (app != null) { 104 | try { 105 | Method close = app.getClass().getDeclaredMethod("close"); 106 | close.setAccessible(true); 107 | close.invoke(app); 108 | } catch (NoSuchMethodException e) {} 109 | } 110 | } 111 | } 112 | 113 | private static final boolean testEnabled(Object object) { 114 | if (object == null) return false; 115 | if (testedAlready.contains(object.getClass())) return false; 116 | try { 117 | Field TESTED=object.getClass().getDeclaredField("TESTED"); 118 | TESTED.setAccessible(true); 119 | return TESTED.getBoolean(object); 120 | } catch(Exception e) {} 121 | return true; 122 | } 123 | 124 | /** test if object of this type has not been already tested */ 125 | public static final T test(T object) { 126 | if (testEnabled(object)) { 127 | testAlways(object); 128 | } 129 | return object; 130 | } 131 | 132 | public static final T untest(T object) { 133 | return object; 134 | } 135 | 136 | public static final T testAlways(T object) { 137 | try { 138 | testedAlready.add(object.getClass()); 139 | DecimalFormat df = new DecimalFormat("0.00"); 140 | Method[] methods = Reflect.getDeclaredMethodsInOrder(object.getClass()); 141 | 142 | for (Method method : methods) { 143 | if (method.getName().startsWith("test") 144 | && method.getParameterTypes().length == 0) { 145 | 146 | kiss.API.seed(1); 147 | method.setAccessible(true); 148 | 149 | Date started = new Date(); 150 | System.out.println(started+" "+method.getName()+": started"); 151 | method.invoke(object); 152 | 153 | Date ended = new Date(); 154 | 155 | double elapsed = (ended.getTime()-started.getTime())/1000.0; 156 | 157 | System.out.println(ended+" "+method.getName()+": ended in " + df.format(elapsed) + " second(s)"); 158 | } 159 | } 160 | return object; 161 | } catch (Exception e) { 162 | throw new AssertionError("test(s) failed",e); 163 | } 164 | 165 | } 166 | 167 | public static final T untestAlways(T object) throws Exception { 168 | return object; 169 | } 170 | 171 | public static final void pause(double duration) { 172 | if (duration > 0) { 173 | try { 174 | duration *= 1000.0; 175 | long millis = (long) (duration); 176 | int nanos = (int) ((duration-millis)*1_000_000.0); 177 | Thread.sleep(millis,nanos); 178 | } catch (InterruptedException e) { 179 | e.printStackTrace(); 180 | } 181 | } else { 182 | Thread.yield(); 183 | } 184 | } 185 | 186 | public static final double time() { 187 | return java.lang.System.currentTimeMillis()/1000.0; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/main/java/kiss/util/Cipher.java: -------------------------------------------------------------------------------- 1 | package kiss.util; 2 | 3 | import javax.crypto.AEADBadTagException; 4 | import java.security.MessageDigest; 5 | import javax.crypto.spec.SecretKeySpec; 6 | import javax.crypto.spec.GCMParameterSpec; 7 | import java.util.Arrays; 8 | import java.nio.charset.Charset; 9 | 10 | public class Cipher { 11 | static char [] codes = new char [] { 12 | '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' 13 | }; 14 | public static void hex(StringBuilder sb, byte[] bin, int offset, int length) { 15 | for (int i=0; i>4) & 0xF)]); 18 | sb.append(codes[((b>>0) & 0xF)]); 19 | } 20 | } 21 | 22 | public static String hex(byte[] bin) { 23 | if (bin == null) return null; 24 | StringBuilder sb = new StringBuilder(bin.length*2); 25 | hex(sb,bin,0,bin.length); 26 | return sb.toString(); 27 | } 28 | 29 | public static byte[] bin(CharSequence hex) { 30 | if (hex == null) return null; 31 | byte[] ans = new byte[(hex.length()+1)/2]; 32 | int j=0; 33 | byte b=0; 34 | for (int i=0; i getClass(Type type) { 23 | if (type instanceof Class) { 24 | return (Class) type; 25 | } 26 | else if (type instanceof ParameterizedType) { 27 | return getClass(((ParameterizedType) type).getRawType()); 28 | } 29 | else if (type instanceof GenericArrayType) { 30 | Type componentType = ((GenericArrayType) type).getGenericComponentType(); 31 | Class componentClass = getClass(componentType); 32 | if (componentClass != null ) { 33 | return Array.newInstance(componentClass, 0).getClass(); 34 | } 35 | else { 36 | return null; 37 | } 38 | } 39 | else { 40 | return null; 41 | } 42 | } 43 | 44 | /** 45 | * 46 | * Rarified code used to discover event listeners for generic Generator 47 | * 48 | * Almost verbatim from: 49 | * 50 | * http://www.artima.com/weblogs/viewpost.jsp?thread=208860 51 | * 52 | */ 53 | public static List> getTypeArguments( 54 | Class baseClass, Class childClass) { 55 | Map resolvedTypes = new HashMap(); 56 | Type type = childClass; 57 | // start walking up the inheritance hierarchy until we hit baseClass 58 | while (! getClass(type).equals(baseClass)) { 59 | if (type instanceof Class) { 60 | // there is no useful information for us in raw types, so just keep going. 61 | type = ((Class) type).getGenericSuperclass(); 62 | } 63 | else { 64 | ParameterizedType parameterizedType = (ParameterizedType) type; 65 | Class rawType = (Class) parameterizedType.getRawType(); 66 | 67 | Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); 68 | TypeVariable[] typeParameters = rawType.getTypeParameters(); 69 | for (int i = 0; i < actualTypeArguments.length; i++) { 70 | resolvedTypes.put(typeParameters[i], actualTypeArguments[i]); 71 | } 72 | 73 | if (!rawType.equals(baseClass)) { 74 | type = rawType.getGenericSuperclass(); 75 | } 76 | } 77 | } 78 | 79 | // finally, for each actual type argument provided to baseClass, determine (if possible) 80 | // the raw class for that type argument. 81 | Type[] actualTypeArguments; 82 | if (type instanceof Class) { 83 | actualTypeArguments = ((Class) type).getTypeParameters(); 84 | } 85 | else { 86 | actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); 87 | } 88 | List> typeArgumentsAsClasses = new ArrayList>(); 89 | // resolve types by chasing down type variables. 90 | for (Type baseType: actualTypeArguments) { 91 | while (resolvedTypes.containsKey(baseType)) { 92 | baseType = resolvedTypes.get(baseType); 93 | } 94 | typeArgumentsAsClasses.add(getClass(baseType)); 95 | } 96 | return typeArgumentsAsClasses; 97 | } 98 | 99 | private static class MethodOffset implements Comparable { 100 | MethodOffset(Method _method, int _offset) { 101 | method=_method; 102 | offset=_offset; 103 | } 104 | 105 | @Override 106 | public int compareTo(MethodOffset target) { 107 | return offset-target.offset; 108 | } 109 | 110 | Method method; 111 | int offset; 112 | } 113 | 114 | static class ByLength implements Comparator { 115 | 116 | @Override 117 | public int compare(Method a, Method b) { 118 | return b.getName().length()-a.getName().length(); 119 | } 120 | } 121 | 122 | /** Grok the bytecode to get the declared order */ 123 | public static Method[] getDeclaredMethodsInOrder(Class clazz) { 124 | Method[] methods = null; 125 | try { 126 | String resource = clazz.getName().replace('.', '/')+".class"; 127 | 128 | methods = clazz.getDeclaredMethods(); 129 | 130 | InputStream is = clazz.getClassLoader() 131 | .getResourceAsStream(resource); 132 | 133 | if (is == null) { 134 | return methods; 135 | } 136 | 137 | java.util.Arrays.sort(methods,new ByLength()); 138 | ArrayList blocks = new ArrayList(); 139 | int length = 0; 140 | for (;;) { 141 | byte[] block = new byte[16*1024]; 142 | int n = is.read(block); 143 | if (n > 0) { 144 | if (n < block.length) { 145 | block = java.util.Arrays.copyOf(block,n); 146 | } 147 | length += block.length; 148 | blocks.add(block); 149 | } else { 150 | break; 151 | } 152 | } 153 | 154 | byte[] data = new byte[length]; 155 | int offset = 0; 156 | for (byte[] block : blocks) { 157 | System.arraycopy(block,0,data,offset,block.length); 158 | offset += block.length; 159 | } 160 | 161 | String sdata = new String(data,java.nio.charset.Charset.forName("UTF-8")); 162 | int lnt = sdata.indexOf("LineNumberTable"); 163 | if (lnt != -1) sdata = sdata.substring(lnt+"LineNumberTable".length()+3); 164 | int cde = sdata.lastIndexOf("SourceFile"); 165 | if (cde != -1) sdata = sdata.substring(0,cde); 166 | 167 | MethodOffset mo[] = new MethodOffset[methods.length]; 168 | 169 | 170 | for (int i=0; i= 0 && 178 | mo[j].offset <= pos && 179 | pos < mo[j].offset + mo[j].method.getName().length()) { 180 | subset = true; 181 | break; 182 | } 183 | } 184 | if (subset) { 185 | pos += methods[i].getName().length(); 186 | } else { 187 | break; 188 | } 189 | } 190 | mo[i] = new MethodOffset(methods[i],pos); 191 | } 192 | java.util.Arrays.sort(mo); 193 | for (int i=0; i pinMap.length 256 | || pinMap[pinNum-1] >= 128 || bcmPins[pinMap[pinNum-1]] == null) { 257 | throw new UnsupportedOperationException("invalid pin " + pinNum); 258 | } 259 | 260 | if (pins[pinNum-1] == null) { 261 | PinMode pinMode = ((mode & 0b100) != 0) ? PinMode.DIGITAL_OUTPUT : PinMode.DIGITAL_INPUT; 262 | PinPullResistance pinPullResistance = null; 263 | 264 | if ((mode & 0b010) != 0) { 265 | if ((mode & 0b001) != 0) { 266 | pinPullResistance = PinPullResistance.PULL_UP; 267 | } else { 268 | pinPullResistance = PinPullResistance.PULL_DOWN; 269 | } 270 | } else { 271 | pinPullResistance = PinPullResistance.OFF; 272 | } 273 | pins[pinNum-1] = gpio.provisionDigitalMultipurposePin(bcmPins[pinMap[pinNum-1]],"pin " + pinNum,pinMode,pinPullResistance); 274 | } 275 | if ((mode & 0b100) != 0) { 276 | pins[pinNum-1].setMode(PinMode.DIGITAL_OUTPUT); 277 | if ((mode & 0b001) != 0) { 278 | pins[pinNum-1].high(); 279 | } else { 280 | pins[pinNum-1].low(); 281 | } 282 | } else { 283 | pins[pinNum-1].setMode(PinMode.DIGITAL_INPUT); 284 | } 285 | } 286 | 287 | public static final void digitalWrite(int pinNum, boolean value) { 288 | GpioPinDigitalMultipurpose pin = pins[pinNum-1]; 289 | if (pin == null) { 290 | pinMode(pinNum,value ? OUTPUT_HIGH : OUTPUT_LOW); 291 | } else { 292 | if (value) { 293 | pin.high(); 294 | } else { 295 | pin.low(); 296 | } 297 | } 298 | } 299 | 300 | public static final boolean digitalRead(int pinNum) { 301 | GpioPinDigitalMultipurpose pin = pins[pinNum-1]; 302 | if (pin == null) { 303 | pinMode(pinNum,INPUT); 304 | return pins[pinNum-1].getState().isHigh(); 305 | } else { 306 | return pin.getState().isHigh(); 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # KISS Java API 4 | 5 | ### Get, Use, or Download 6 | 7 | [kiss releases](https://github.com/wmacevoy/kiss/releases) 8 | 9 | [maven complete pom] (examples/helloworld/pom.xml) 10 | ```xml 11 | 12 | ... 13 | 14 | 15 | com.github.wmacevoy 16 | kiss 17 | LATEST 18 | 19 | ... 20 | 21 | ... 22 | 23 | ``` 24 | 25 | ## Why KISS Java? 26 | 27 | KISS keeps it simple, so Java can be used to teach software development concepts. 28 | * Simplified run, testing, input, output, math, casting, events and ciphers. 29 | * Just one jar file with no dependencies available as release and hosted on maven central. 30 | * [Instructor video: why kiss?](https://youtu.be/YiftHVmbxgU) 31 | * [Student videos: getting started](https://www.youtube.com/channel/UC5Fchcau0ofytGrUbQd_J0w) 32 | 33 | ## Hello, World! 34 | There is no need to understand packages, static methods, access modifiers, arrays, or method invocations to write simple programs. Here is "Hello World!": 35 | ```java 36 | import static kiss.API.*; 37 | 38 | class App { 39 | void run() { 40 | println("Hello, World!"); 41 | } 42 | } 43 | ``` 44 | To see the classic message, you need the kiss JAR file in your project and use "kiss.API" as your main class. If you use Maven (supported by most common IDE's) there are pre-built `pom.xml` files in the example projects. 45 | 46 | ## "Hello World!", Tested!! 47 | Wouldn't it be nice to introduce testing right away? 48 | ```java 49 | import static kiss.API.*; 50 | 51 | class App { 52 | void testRun() { 53 | outExpect("Hello, World!"); 54 | run(); 55 | outClose(); 56 | } 57 | void run() { 58 | println("Hello, World!"); 59 | } 60 | } 61 | ``` 62 | 63 | Any `testXXX` method is automatically called before the `run` method. Want to write a test? Just write the test! 64 | 65 | Or, since you can't write much Java without a try block anyway, a better version is: 66 | ```java 67 | import static kiss.API.*; 68 | 69 | class App { 70 | void testRun() { 71 | try (Close out=outExpect("Hello, World!")) { 72 | run(); 73 | } 74 | } 75 | 76 | void run() { 77 | println("Hello, World!"); 78 | } 79 | } 80 | ``` 81 | 82 | ## Randomness a kindergartener understands 83 | 84 | `int die=random(1,6)` is a die roll and `seed(1)` resets the pseudo-random sequence for testability. The random-number sequence is reset with `seed(1)` before each `textXXX()` and reset to a cryptographically strong PRNG with `seed()` before invoking `run()`. It is also about twice as fast as the normal random number generator. 85 | 86 | ## ~~Math~~.math 87 | 88 | The java.Math static methods are effectively also imported, so you just use `sqrt`, not `Math.sqrt`. Peppering 'Math.' in all your formulas does not make you smarter or the code easier to read. 89 | 90 | ## Obvious Output 91 | 92 | Here is a Java program that makes a space-separated CSV file 93 | with 100 die rolls pairs: 94 | 95 | ```java 96 | import static kiss.API.*; 97 | 98 | class App { 99 | void run() { 100 | outOpen("rolls.csv"); 101 | println("i d1 d2 sum"); 102 | for (int i=1; i<=100; ++i) { 103 | int d1=random(1,6); 104 | int d2=random(1,6); 105 | int sum=d1+d2; 106 | println(i,d1,d2,sum); 107 | } 108 | outClose(); 109 | } 110 | } 111 | ``` 112 | 113 | ## Intuitive Input 114 | 115 | ```java 116 | import static kiss.API.*; 117 | 118 | class App { 119 | void run() { 120 | print("time(seconds)? "); 121 | double t = readDouble(); 122 | print("gravity(meters/second^2)? "); 123 | double g = readDouble(); 124 | double d =0.5*g*pow(t,2); 125 | println("It fell " + d + " meters."); 126 | } 127 | } 128 | ``` 129 | 130 | You can get input from a file with 131 | 132 | ```java 133 | inOpen(filename); 134 | XX value = readXX(); 135 | ... 136 | inClose(); 137 | ``` 138 | 139 | ## Goodness by section 140 | 141 | ### Run 142 | 143 | The `Run` part of the kiss API simplifies starting and controlling the execution of your application. It contains a `main()` method to launch your application which does the following 144 | 145 | 1. Run looks for the application class. This is `App` in the default (no declaration) package. If you want to use some other class, just pass the `--app ` argument on the command line, or specify it with the `JAVA_APP` environment variable. 146 | 147 | 2. Run constructs an instance of the application class using the default constructor. The constructor (or anywhere else) can use APP_ARGS to access command line arguments and APP_NAME contains the class name of the application object. After the instance is constructed (at the end of this step), APP is a global reference to the application object. 148 | 149 | 3. Run invokes all testXXX() methods in order of declaration. The random 150 | number generator is reset with `seed(1)` before each test to help make the 151 | tests reproducible. You can skip invoking tests with the `--notest` option. 152 | 153 | 4. Run invokes the run() method. The random number generator is set to 154 | produce a strongly random sequence before this. You can skip invoking 155 | run with the `--norun` option. 156 | 157 | 5. Run invokes the close method, even if there was an error in a test or run. 158 | 159 | All the steps after the construction are optional. 160 | 161 | ### `kiss.util.Run` components of the `kiss.API` 162 | 163 | * `test(Target target)` --- test components other than the main application. This can be used at the point of creation, as in: 164 | ```java 165 | MyComponent myComponent=test(new MyComponent()) 166 | ``` 167 | Only the first instance of an object is tested (or use `testAlways` instead). If you want to skip testing of an object, replace `test` with `untest`. 168 | 169 | * `pause(double duration)` --- Pauses the application for the given number of seconds (without wasting CPU time). 170 | 171 | * `double time()` --- Returns the seconds since midnight, January 1, 1970 UTC. Calling this twice and taking the difference is useful for interval timing. 172 | 173 | * `String APP_NAME` --- The name of the application class (just `"App"` by default) 174 | 175 | * `String[] APP_ARGS` --- The command line arguments. 176 | 177 | * `Object APP` --- Once the application object is constructed, this is a global reference to the application object. 178 | 179 | ### I/O 180 | 181 | * `outOpen(String filename)` --- redirects print/ln() output to the specified 182 | file. These can be nested and each thread is independent. There must be a 183 | matching `outClose()` to close the file. The best-practice pattern is a try-with-resources: 184 | ```java 185 | try (Close out=outOpen("hi.txt")) { 186 | println("hi!"); 187 | } 188 | ``` 189 | This assures the file is closed, even in the case of an error. 190 | 191 | * `inOpen(String filename)` --- redirects readXXX() to use this input file. These can be nested and each thread is independent. There must be a matching `inClose()` to close the file. The best-practice pattern is a try-with-resources: 192 | ```java 193 | try (Close in=inOpen("words.txt")) { 194 | String word = readLine(); 195 | // do something with word. 196 | } 197 | ``` 198 | This assures the file is closed, even in the case of an error. 199 | 200 | * `print/ln(...)` --- like PrintStream's print/ln, but it sends the formatted strings to the current output stream (`System.out` by default) and does a nicer job with arrays and collections. You can change the default output with `outOpen`, `outExpect`, and `outVerify`. 201 | 202 | * `outExpect(...)` --- makes an internal stream which is used to match against future output (until `inClose()` or the end of the try block). If there is a mismatch an error is thrown. 203 | 204 | * `readXXX(...)` --- uses a `java.util.Scanner` on the current input stream (`System.in` by default). You can change the default with `inOpen` and `inProvide`. 205 | 206 | * `inProvide(...)` --- makes an internal stream which is used for future input (until `inClose()` or the end of the try block). 207 | 208 | * `outVerify(String filename)` --- like `outExpect`, but matches against an external file for more complicated output. 209 | 210 | ### Math 211 | 212 | All the math functions and constants are imported, with the exception of `Math.random()` and `Math.random(int n)` which are replaced by improved versions. 213 | 214 | ### RNG 215 | 216 | A fast (faster than the standard random number generator), but cryptographically strong pseudo-random number generator is provided by default. Calling `seed()` strongly sets the seed, while `seed(double value)` sets it to a reproducible sequence. 217 | 218 | * `int random(int a, int b)` --- generates a uniformly random integer in the interval, including the endpoints. If b<=a, this always returns a. 219 | 220 | * `int random(int n)` --- same as `random(0,n-1)`. 221 | 222 | * `double random()` --- returns a uniformly random double in the interval [0,1). 223 | 224 | * `seed()` --- seeds the PRNG with a 128-bit strong random seed. 225 | 226 | * `seed(double value)` --- seeds the PRNG for a reproducible sequence. 227 | 228 | ### Events 229 | 230 | The generator/event/listener pattern is all over the JDK, because it helps solve the hard problem of hooking different objects together to solve a larger problem, even if the generators and listeners didn't know much about each other to start with. 231 | 232 | But most tutorials on it are a secret apology: they discuss how to "listen" to events/messages but "generating" events/messages is either done badly or not at all. With kiss, it is easy to do it right without advanced Java katas: 233 | 234 | ```java 235 | import static kiss.API.*; 236 | 237 | class Parrot { 238 | void mimic(String words) { 239 | println("squawk: " + words + "!"); 240 | } 241 | }; 242 | 243 | class Trainer extends Generator { 244 | void speak(String words) { send(words); } 245 | } 246 | 247 | class App { 248 | void run() { 249 | Parrot polly = new Parrot(); 250 | Trainer susan = new Trainer(); 251 | 252 | susan.addListener(words -> polly.mimic(words)); 253 | 254 | susan.speak("hello"); 255 | } 256 | } 257 | ``` 258 | This produces `squawk: hello!` 259 | 260 | ### As 261 | 262 | The casting notation is hard to read and converting strings to primitives types 263 | is a pile of API and inconsistent with the syntax of the language. So, 264 | ```java 265 | assert asDouble(3)/asDouble(2) == 1.5; 266 | assert asInt("0xff_ff") == 0xff_ff; 267 | assert asString('a').equals("a"); 268 | assert asChar("a") == 'a'; 269 | assert asBoolean(0) == false; 270 | assert asBoolean(1) == true; 271 | ``` 272 | 273 | ### Crypt 274 | 275 | Simple to use, but strong symmetric key encryption. 276 | 277 | * String encrypt(String key, String plain) --- Encrypt message with key producing a hex encoded string (changed in v1.1 compared to previous version). 278 | 279 | * String decrypt(String key, String secret) --- Decrypt a hex encoded string (like those made by encrypt) to recreate the message (changed in v1.1 compared to previous version). 280 | 281 | * String sha256(String text) --- Common secure hash. 282 | 283 | [logo]: kiss/java-kiss.png "Java Duke with Kiss" 284 | 285 | [1] [Orignal Java Duke image on wikipedia](https://en.wikipedia.org/wiki/Java_(programming_language)#/media/File:Wave.svg) 286 | 287 | [2] [Original public domain kiss image on pixabay](https://pixabay.com/en/lips-mouth-speak-kiss-lipstick-145758/) 288 | 289 | 290 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------