From dbd679fa2a7e82c27da26eafd3a266c9171a8482 Mon Sep 17 00:00:00 2001 From: Aaronepower Date: Tue, 26 May 2015 22:00:12 +0100 Subject: [PATCH] First draft of Rusty CLOC --- .gitignore | 1 + Cargo.lock | 34 ++ Cargo.toml | 15 + src/language.rs | 52 +++ src/main.rs | 183 ++++++++ src/test/Another document.txt | 0 src/test/Cmder.exe | Bin 0 -> 31744 bytes src/test/JavaScript/APIService.js | 35 ++ src/test/JavaScript/CallService.js | 55 +++ src/test/JavaScript/TokenService.js | 27 ++ src/test/JavaScript/UserService.js | 60 +++ src/test/Rust/main.rs | 66 +++ src/test/Test document.txt | 44 ++ src/test/cpp/cppkoans.cpp | 77 ++++ src/test/cpp/header/all_koans.hpp | 35 ++ src/test/cpp/header/fill_me_in_exception.hpp | 66 +++ src/test/cpp/header/koan.hpp | 40 ++ src/test/cpp/header/koan00_get_started.hpp | 71 +++ src/test/cpp/header/koan01_number_types.hpp | 91 ++++ .../cpp/header/koan02_character_types.hpp | 80 ++++ src/test/cpp/header/koan03_further_types.hpp | 75 +++ src/test/cpp/header/koan04_arrays.hpp | 76 ++++ src/test/cpp/header/koan05_pointers.hpp | 81 ++++ src/test/cpp/header/koanXX_sample_koans.hpp | 80 ++++ src/test/cpp/header/koan_handler.cpp | 101 +++++ src/test/cpp/header/koan_handler.hpp | 90 ++++ src/test/css/normalize.css | 427 ++++++++++++++++++ src/test/css/skeleton.css | 418 +++++++++++++++++ src/test/css/style.css | 201 +++++++++ src/test/java/StudentNetworkSimulator.java | 248 ++++++++++ src/test/python_script.py | 21 + 31 files changed, 2850 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/language.rs create mode 100644 src/main.rs create mode 100644 src/test/Another document.txt create mode 100644 src/test/Cmder.exe create mode 100644 src/test/JavaScript/APIService.js create mode 100644 src/test/JavaScript/CallService.js create mode 100644 src/test/JavaScript/TokenService.js create mode 100644 src/test/JavaScript/UserService.js create mode 100644 src/test/Rust/main.rs create mode 100644 src/test/Test document.txt create mode 100644 src/test/cpp/cppkoans.cpp create mode 100644 src/test/cpp/header/all_koans.hpp create mode 100644 src/test/cpp/header/fill_me_in_exception.hpp create mode 100644 src/test/cpp/header/koan.hpp create mode 100644 src/test/cpp/header/koan00_get_started.hpp create mode 100644 src/test/cpp/header/koan01_number_types.hpp create mode 100644 src/test/cpp/header/koan02_character_types.hpp create mode 100644 src/test/cpp/header/koan03_further_types.hpp create mode 100644 src/test/cpp/header/koan04_arrays.hpp create mode 100644 src/test/cpp/header/koan05_pointers.hpp create mode 100644 src/test/cpp/header/koanXX_sample_koans.hpp create mode 100644 src/test/cpp/header/koan_handler.cpp create mode 100644 src/test/cpp/header/koan_handler.hpp create mode 100644 src/test/css/normalize.css create mode 100644 src/test/css/skeleton.css create mode 100644 src/test/css/style.css create mode 100644 src/test/java/StudentNetworkSimulator.java create mode 100644 src/test/python_script.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..606a548 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,34 @@ +[root] +name = "rusty-cloc" +version = "0.1.0" +dependencies = [ + "getopts 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getopts" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..37c417f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rusty-cloc" +version = "0.1.0" +authors = ["Aaronepower "] + +[dependencies] +getopts = "0.2" +glob = "*" + +[profile.dev] +debug = true + + +[profile.release] +opt-level = 3 \ No newline at end of file diff --git a/src/language.rs b/src/language.rs new file mode 100644 index 0000000..3606872 --- /dev/null +++ b/src/language.rs @@ -0,0 +1,52 @@ +use std::fmt; + +pub struct Language<'a> { + pub name: &'a str, + pub line_comment: &'a str, + pub multi_line: &'a str, + pub multi_line_end: &'a str, + pub files: Vec, + pub code: u32, + pub comments: u32, + pub blanks: u32, + pub lines: u32, + pub total: usize, +} + +impl<'a> Language<'a> { + pub fn new<'b>(name: &'a str, + line_comment: &'a str, + multi_line: &'a str, + multi_line_end: &'a str) -> Language<'a> { + + Language { + name: name, + line_comment: line_comment, + multi_line: multi_line, + multi_line_end: multi_line_end, + files: Vec::new(), + code: 0, + comments: 0, + blanks: 0, + lines: 0, + total: 0, + } + } + + pub fn is_empty(&self) -> bool { + self.code == 0 && self.comments == 0 && self.blanks == 0 && self.lines == 0 + } +} + +impl<'a> fmt::Display for Language<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut total; + + if self.total == 0 { + total = self.files.len() + } else { + total = self.total; + } + write!(f," {: <15} {: >15} {:>15} {:>15} {:>15} {:>15} ", self.name, total, self.lines, self.blanks, self.comments, self.code) + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..998aee1 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,183 @@ +extern crate getopts; +extern crate glob; + +pub mod language; + +use std::env; +use std::fs; +use std::io::Read; +use std::path::Path; +use std::fs::{File, metadata}; +use std::collections::HashMap; +use self::glob::glob; +use getopts::Options; +use language::Language; + +fn main() { + let args: Vec = env::args().collect(); + let mut opts = Options::new(); + + opts.optflag("h", "help", "Print this help menu"); + opts.optopt("", "exclude-dir", "Example: --exclude-dir=docs", "\tDirectories wanted to be ignored"); + + let matches = opts.parse(&args[1..]).unwrap(); + let mut ignored_directories: Vec = Vec::new(); + ignored_directories.push(".git".to_string()); + + if matches.opt_present("h") { + let brief = format!("Usage: {} [options] [paths]", args[0].clone()); + println!("{}", opts.usage(&brief)); + return; + } + + if matches.opt_present("exclude-dir") { + let exclude_args = matches.opt_str("exclude-dir").unwrap(); + let exclude_vec = exclude_args.split(","); + + + for excluded in exclude_vec { + ignored_directories.push(excluded.to_string()); + } + } + + if !matches.free.is_empty() { + println!("----------------------------------------------------------------------------------------------------"); + println!(" {:<15} {:>15} {:>15} {:>15} {:>15} {:>15} ", + "language", "files", "total", "blanks", "comments", "code"); + println!("----------------------------------------------------------------------------------------------------"); + let mut languages: HashMap<&str, Language> = HashMap::new(); + languages.insert("cpp" , Language::new("C++", "//","/*","*/")); + languages.insert("hpp" , Language::new("C++ Header", "//","/*","*/")); + languages.insert("c" , Language::new("C", "//","/*","*/")); + languages.insert("h" , Language::new("C Header", "//","/*","*/")); + languages.insert("css" , Language::new("CSS", "//","/*","*/")); + languages.insert("java" , Language::new("Java", "//","/*","*/")); + languages.insert("js" , Language::new("JavaScript", "//","/*","*/")); + languages.insert("rs" , Language::new("Rust", "//","/*","*/")); + languages.insert("xml" , Language::new("XML", "")); + languages.insert("html" , Language::new("HTML", "")); + languages.insert("py" , Language::new("Python", "#","'''","'''")); + languages.insert("rb" , Language::new("Ruby", "#","=begin","=end")); + + for path in matches.free { + let files = get_all_files(path, &ignored_directories); + + for file in files { + let extension = match Path::new(&file).extension() { + Some(result) => result.to_str().unwrap(), + None => continue, + }; + + let mut language = match languages.get_mut(extension) { + Some(result) => result, + None => continue, + }; + language.files.push(file.to_string()); + } + } + + let mut total = Language::new("Total", "", "", ""); + + for (_, language) in languages.iter_mut() { + + for file in language.files.iter() { + let mut buffer: Vec = Vec::new(); + + let mut file_ref = match File::open(&file) { + Ok(result) => result, + _ => continue, + }; + + let _ = file_ref.read_to_end(&mut buffer); + + let contents = match String::from_utf8(buffer) { + Ok(result) => result, + Err(_) => continue, + }; + + let mut is_in_comments = false; + + for line in contents.lines() { + let line = line.trim(); + language.lines += 1; + + if line.starts_with(language.multi_line) { + language.comments += 1; + is_in_comments = true; + } else if line.contains(language.multi_line) { + language.code += 1; + is_in_comments = true; + } + + if is_in_comments { + if line.contains(language.multi_line_end) { + is_in_comments = false; + } + language.comments += 1; + continue; + } + + if line.starts_with(language.line_comment) { + language.comments += 1; + } else if line.trim().is_empty() { + language.blanks += 1; + } else { + language.code += 1; + } + }; + } + if !language.is_empty() { + println!("{}", language); + } + total.total += language.files.len(); + total.lines += language.lines; + total.comments += language.comments; + total.blanks += language.blanks; + total.code += language.code; + } + println!("----------------------------------------------------------------------------------------------------"); + println!("{}", total); + println!("----------------------------------------------------------------------------------------------------"); + } +} + + + +fn get_all_files(path: String, ignored_directories: &Vec) -> Vec { + let mut files: Vec = Vec::new(); + + if let Ok(result) = metadata(&path) { + if result.is_dir() { + let dir = fs::read_dir(&path).unwrap(); + 'file: for entry in dir { + let dir_entry = entry.unwrap(); + let file_path = dir_entry.path(); + let file_str = file_path.to_str().unwrap(); + let file_string = file_str.to_string(); + let path_metadata = metadata(&file_string).unwrap(); + + if path_metadata.is_dir() { + for ignored_directory in ignored_directories { + if file_str.contains(ignored_directory) { + continue 'file; + } + } + for file in get_all_files(file_string, &ignored_directories) { + files.push(file); + } + } else if path_metadata.is_file() { + files.push(file_string); + } + } + } else { + files.push(path); + } + } else { + for path_buf in glob(&path).unwrap() { + let file_path = path_buf.unwrap().as_path().to_str().unwrap().to_string(); + files.push(file_path); + } + } + + files +} \ No newline at end of file diff --git a/src/test/Another document.txt b/src/test/Another document.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/test/Cmder.exe b/src/test/Cmder.exe new file mode 100644 index 0000000000000000000000000000000000000000..f5cab6d7aca8c2fef59b218fc1ff8c0b329b3582 GIT binary patch literal 31744 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 F_<#6T7Bc_< literal 0 HcmV?d00001 diff --git a/src/test/JavaScript/APIService.js b/src/test/JavaScript/APIService.js new file mode 100644 index 0000000..b2bf542 --- /dev/null +++ b/src/test/JavaScript/APIService.js @@ -0,0 +1,35 @@ +function APIService ($http, $resource, TokenService) { + + var usersRoute = '/api/users/' + + var User = $resource( usersRoute + , {} + , { signin : { method : 'POST' + , url : usersRoute+'signin' + } + + , update : { method : 'PUT' + } + + , add : { method: 'POST' + , url : usersRoute+'add' + } + + , accept : { method: 'POST' + , url : usersRoute+'accept' + } + + , remove : { method : 'POST' + , url : usersRoute+'remove' + } + + , validate : { method : 'GET' + , url : usersRoute+'validate' + } + } + ) + return User +} + +angular.module('Echo') + .factory('API', APIService) diff --git a/src/test/JavaScript/CallService.js b/src/test/JavaScript/CallService.js new file mode 100644 index 0000000..ef2c92d --- /dev/null +++ b/src/test/JavaScript/CallService.js @@ -0,0 +1,55 @@ +function CallService (UserService) { + var webrtc + + function startCall(ID) { + webrtc = new SimpleWebRTC({ + localVideoEl: 'local', + remoteVideosEl: 'remotes', + autoRequestMedia: true + }) + + webrtc.on('readyToCall', function () { + webrtc.joinRoom(ID) + }) + } + + function endCall() { + webrtc.disconnect() + } + + function sendOffer() { + console.log(UserService.getUser()) + console.log(UserService.getUserID()) + socket.emit('callOffer', UserService.getUserID(), UserService.getFriend()) + + socket.on('callAccepted', function (receiverID) { + startCall(receiverID) + }) + + socket.on('callRejected', function (receiverID) { + // TODO Replace in the UI + alert('User is busy,') + }) + } + + socket.on('callOffer', function (senderID) { + console.log('Call Offered from: '+senderID) + // TODO Replace within the UI + var callConfirm = confirm(senderID+' is calling you. Accept?') + + if (callConfirm) { + socket.emit('callAccepted', senderID, UserService.getUserID()) + startCall(UserService.getUserID()) + } + else { + socket.emit('callRejected', senderID, UserService.getID()) + } + }) + + return { sendOffer : sendOffer + , endCall : endCall + } +} + +angular.module('Echo') +.factory('CallService', CallService) diff --git a/src/test/JavaScript/TokenService.js b/src/test/JavaScript/TokenService.js new file mode 100644 index 0000000..e2f7a12 --- /dev/null +++ b/src/test/JavaScript/TokenService.js @@ -0,0 +1,27 @@ +function TokenService ($window) { + var tokenKey = 'Token' + function getToken () { + return $window.localStorage.getItem(tokenKey) + } + + function setToken (token) { + $window.localStorage.setItem(tokenKey, token) + console.log('Token set: ', token) + tokenService.token = getToken() + } + + function tokenExists () { + return getToken() !== null + } + + var tokenService = { getToken : getToken + , setToken : setToken + , tokenExists : tokenExists + , token : getToken() + } + + return tokenService +} + +angular.module('Echo') + .factory('TokenService', TokenService) diff --git a/src/test/JavaScript/UserService.js b/src/test/JavaScript/UserService.js new file mode 100644 index 0000000..402f8cd --- /dev/null +++ b/src/test/JavaScript/UserService.js @@ -0,0 +1,60 @@ +function UserService ($location, jwtHelper, TokenService) { + var user + , friendID = '' + + function createUser (token) { + user = jwtHelper.decodeToken(token) + var event = new CustomEvent('userCreated', {detail : user}) + document.dispatchEvent(event) + } + + function getUser () { + return user + } + + function getUserID () { + return user._id + } + + function setFriend(newFriendID) { + friendID = newFriendID + } + + function getFriend () { + return friendID + } + + function loginEvent (token) { + createUser(token) + TokenService.setToken(token) + socket.emit('logged-in', getUserID()) + } + /* + Hi + + This should be 5 + + Thanks + */ + function loginSuccess(response) { + loginEvent(response.token) + $location.path('/dashboard') + } + + function loginError (response) { + // TODO show errors to user + console.log(response.status) + } + return { createUser : createUser + , loginSuccess : loginSuccess + , loginError : loginError + , loginEvent : loginEvent + , getUser : getUser + , getUserID : getUserID + , setFriend : setFriend + , getFriend : getFriend + } +} + +angular.module('Echo') + .factory('UserService', UserService) diff --git a/src/test/Rust/main.rs b/src/test/Rust/main.rs new file mode 100644 index 0000000..f6db0f3 --- /dev/null +++ b/src/test/Rust/main.rs @@ -0,0 +1,66 @@ +use std::thread; + +use std::sync::{Mutex, Arc}; + +struct Table { + forks: Vec>, +} + +struct Philosopher { + name: String, + left: usize, + right: usize, +} + +impl Philosopher { + fn new(name: &str, left: usize, right: usize) -> Philosopher { + Philosopher { + name: name.to_string(), + left: left, + right: right, + } + } + + fn eat(&self, table: &Table) { /* + This should be 2 + */ + + let _left = table.forks[self.left].lock().unwrap(); + let _right = table.forks[self.right].lock().unwrap(); + println!("{} is eating.", self.name); + + thread::sleep_ms(1000); + + println!("{} is done eating.", self.name); + } +} + +fn main() { + + let table = Arc::new(Table { forks: vec![ + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), + Mutex::new(()), + ]}); + + let philosophers = vec![ + Philosopher::new("Baruch Spinoza", 0, 1), + Philosopher::new("Gilles Deleuze", 1, 2), + Philosopher::new("Karl Marx", 2, 3), + Philosopher::new("Friedrich Nietzsche", 3, 4), + Philosopher::new("Michel Foucault", 0, 4), + ]; + + let handles: Vec<_> = philosophers.into_iter().map(|p| { + let table = table.clone(); + thread::spawn(move || { + p.eat(&table); + }) + }).collect(); + + for h in handles { + h.join().unwrap(); + } +} \ No newline at end of file diff --git a/src/test/Test document.txt b/src/test/Test document.txt new file mode 100644 index 0000000..29c62ca --- /dev/null +++ b/src/test/Test document.txt @@ -0,0 +1,44 @@ + + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec lacus vitae augue rhoncus +commodo eu vitae enim. Donec dignissim orci efficitur pellentesque consequat. Nam risus odio, +euismod nec aliquam ut, sollicitudin at orci. Curabitur volutpat porttitor nisl quis venenatis. + Mauris et urna massa. In eu gravida magna. Nunc rutrum tincidunt nisl, eget ullamcorper ipsum +consectetur suscipit. Ut non turpis in risus tempor hendrerit sed at leo. In ut lectus a felis +tempor egestas eu at purus. Integer volutpat nec est sed convallis. Nulla mollis odio vitae nisi + semper hendrerit. Donec vestibulum urna sed porta lacinia. Vestibulum vehicula nulla vel orci +posuere condimentum. Donec at ligula viverra, ornare augue at, commodo risus. + +Pellentesque eu euismod nisl. Duis non neque cursus erat condimentum facilisis quis sed ante. In +fringilla augue sit amet eros imperdiet, in tincidunt lectus tincidunt. In cursus condimentum +blandit. Quisque rutrum elit nec est euismod ultricies. Nam elementum nibh dignissim dapibus +convallis. Donec et faucibus ipsum. Ut egestas, ante vitae gravida commodo, massa neque commodo +nisi, in convallis turpis sapien sagittis sapien. Etiam cursus urna in risus feugiat malesuada. + Pellentesque vitae ligula et nunc luctus pretium quis quis sem. Sed lobortis facilisis nisl, nec + cursus arcu porttitor ac. Curabitur tincidunt facilisis tortor, ut mollis nibh scelerisque in. +Aenean in justo at quam bibendum hendrerit eu quis eros. + + + +Aenean et purus ut ipsum ultrices tempus. Integer hendrerit quis sem eu tempor. Mauris condimentum +nisi eu lobortis hendrerit. Curabitur et pretium odio. Vestibulum hendrerit ipsum consectetur, +commodo ante eget, interdum nibh. Donec ullamcorper nunc ac massa laoreet tristique. Morbi quis +pharetra ligula. Duis ornare in sapien vulputate fermentum. Vivamus non hendrerit nunc. + + +Nulla sit amet nibh justo. Aliquam turpis lectus, venenatis quis nibh sit amet, semper imperdiet + metus. Etiam a ante metus. Nam egestas ut velit sit amet bibendum. Phasellus sollicitudin sodales + diam, a finibus nisl vestibulum eu. Proin eget felis enim. Praesent luctus ut velit imperdiet +pharetra. Etiam laoreet libero et lorem iaculis, bibendum mollis lorem lobortis. Integer lobortis +tristique arcu non ultrices. + + +Praesent cursus lorem a erat consequat, eget efficitur erat viverra. Ut dignissim nunc vitae dolor + cursus, a sodales nunc fermentum. Ut nec euismod sapien, vitae dignissim augue. Morbi est erat, +consequat non ornare eu, molestie non urna. Vestibulum sit amet metus non ligula ultricies sodales + ut et tortor. Praesent congue auctor erat, ac scelerisque nibh ultrices at. Pellentesque euismod +odio ac massa pulvinar consequat vel eget neque. Nunc ut felis id dui consequat hendrerit. Nulla +volutpat ultrices mauris eu aliquam. Nullam sit amet tortor gravida quam fringilla tempor. Aenean +vitae odio elementum, blandit odio quis, convallis odio. Pellentesque habitant morbi tristique +senectus et netus et malesuada fames ac turpis egestas. Nunc gravida vel mi in gravida. +Pellentesque libero sem, tincidunt nec tellus eu, consectetur sollicitudin nunc. diff --git a/src/test/cpp/cppkoans.cpp b/src/test/cpp/cppkoans.cpp new file mode 100644 index 0000000..a854038 --- /dev/null +++ b/src/test/cpp/cppkoans.cpp @@ -0,0 +1,77 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include +#include "headers/koan_handler.hpp" +#include "headers/all_koans.hpp" + +using namespace std; + +/** + * + */ +int main() +{ + KoanHandler status; + + // Koan 00: getting started + Koan00_get_started koan00 = Koan00_get_started( &status ); + + // Koan 01: number types + Koan01_number_types koan01 = Koan01_number_types( &status ); + + // Koan 02: character types + Koan02_character_types koan02 = Koan02_character_types( &status ); + + // Koan 03: further types + Koan03_further_types koan03 = Koan03_further_types( &status ); + + // Koan 04: arrays + Koan04_arrays koan04 = Koan04_arrays( &status ); + + // Koan 05: pointers + Koan05_pointers koan05 = Koan05_pointers( &status ); + + // Koan XX: sample koans +// KoanXX_sample_koans koanXX = KoanXX_sample_koans( &status ); + + // Welcome message + status.start(); + + // The Path of Enlightment + koan00.run(); + koan01.run(); + koan02.run(); + koan03.run(); + koan04.run(); + koan05.run(); +// koanXX.run(); + + // Done. + status.end(); + return( 0 ); +} + +// EOF diff --git a/src/test/cpp/header/all_koans.hpp b/src/test/cpp/header/all_koans.hpp new file mode 100644 index 0000000..8d80d37 --- /dev/null +++ b/src/test/cpp/header/all_koans.hpp @@ -0,0 +1,35 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "koan00_get_started.hpp" +#include "koan01_number_types.hpp" +#include "koan02_character_types.hpp" +#include "koan03_further_types.hpp" +#include "koan04_arrays.hpp" +#include "koan05_pointers.hpp" +// When an episode of koans is added, it must be appended here +// #include "koanXX_sample_koans.hpp" + +// EOF diff --git a/src/test/cpp/header/fill_me_in_exception.hpp b/src/test/cpp/header/fill_me_in_exception.hpp new file mode 100644 index 0000000..17d24a8 --- /dev/null +++ b/src/test/cpp/header/fill_me_in_exception.hpp @@ -0,0 +1,66 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef FILL_ME_IN_HPP +#define FILL_ME_IN_HPP + +#include +#include + +class FillMeInException +{ + public: + std::string file; + int line; + std::string msg; + std::string expect; + FillMeInException( const std::string f, const int l, std::string s ) : file( f ), line( l ), msg( s ) { + file = file.substr( file.find_last_of( "/" ) + 1 ); + } + FillMeInException( const std::string f, const int l, std::string s, std::string e ) : file( f ), line( l ), msg( s ), expect( e ) { + file = file.substr( file.find_last_of( "/" ) + 1 ); + } + ~FillMeInException() {} +}; + +#define ASSERT_MSG(expr, msg) do { \ + if (!(expr)) \ + { \ + throw FillMeInException(__FILE__, __LINE__, msg); \ + }; \ + } while(0) + +#define ASSERT(expr) ASSERT_MSG(expr, "") +#define ASSERT_EQUAL(a, b) ASSERT_EQUAL_MSG(a, b, "") +#define ASSERT_EQUAL_MSG(a, b, msg) do { \ + if (!(a == b)) \ + { \ + std::ostringstream expect;\ + expect << a;\ + throw FillMeInException(__FILE__, __LINE__, msg, expect.str()); \ + }; \ + } while(0) + +#endif diff --git a/src/test/cpp/header/koan.hpp b/src/test/cpp/header/koan.hpp new file mode 100644 index 0000000..7353403 --- /dev/null +++ b/src/test/cpp/header/koan.hpp @@ -0,0 +1,40 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef KOAN_HPP +#define KOAN_HPP + +#include + +using namespace std; + +/** + * + */ +class Koan {}; + +#endif // KOAN_HPP + +// EOF diff --git a/src/test/cpp/header/koan00_get_started.hpp b/src/test/cpp/header/koan00_get_started.hpp new file mode 100644 index 0000000..5428504 --- /dev/null +++ b/src/test/cpp/header/koan00_get_started.hpp @@ -0,0 +1,71 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN00_GET_STARTED_HPP +#define KOAN00_GET_STARTED_HPP + +using namespace std; + +/** + * + */ +class Koan00_get_started : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 1; //! + + public: + /** + * + */ + Koan00_get_started( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan00_get_started() {} + + /** + * + */ + void run() { + status->episode_start( "first" ); + + status->eval_koan( *this, static_cast( &Koan00_get_started::cpp_is_not_too_hard ) ); + + status->episode_done( "first" ); + } + + private: + void cpp_is_not_too_hard(); +}; + +#endif // KOAN00_GET_STARTED_HPP + +// EOF diff --git a/src/test/cpp/header/koan01_number_types.hpp b/src/test/cpp/header/koan01_number_types.hpp new file mode 100644 index 0000000..ca4bfe5 --- /dev/null +++ b/src/test/cpp/header/koan01_number_types.hpp @@ -0,0 +1,91 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN01_NUMBER_TYPES_HPP +#define KOAN01_NUMBER_TYPES_HPP + +/** + * + */ +class Koan01_number_types : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 8; //! + + public: + /** + * + */ + Koan01_number_types( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan01_number_types() {} + + /** + * + */ + void run() { + status->episode_start( "second" ); + + status->eval_koan( *this, static_cast( &Koan01_number_types::simple_integer_numbers ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::integers_have_a_size ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::integers_can_be_negative ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::simple_floats ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::floats_have_a_size ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::going_double_precision ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::doubles_have_a_size ) ); + status->eval_koan( *this, static_cast( &Koan01_number_types::size_of_biggest_number ) ); + + status->episode_done( "second" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void simple_integer_numbers(); + void integers_have_a_size(); + void integers_can_be_negative(); + void simple_floats(); + void floats_have_a_size(); + void going_double_precision(); + void doubles_have_a_size(); + void size_of_biggest_number(); +}; + +#endif // KOAN01_NUMBER_TYPES_HPP + +// EOF diff --git a/src/test/cpp/header/koan02_character_types.hpp b/src/test/cpp/header/koan02_character_types.hpp new file mode 100644 index 0000000..e319501 --- /dev/null +++ b/src/test/cpp/header/koan02_character_types.hpp @@ -0,0 +1,80 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN02_CHARACTER_TYPES_HPP +#define KOAN02_CHARACTER_TYPES_HPP + +class Koan02_character_types : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 4; //! + + public: + /** + * + */ + Koan02_character_types( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan02_character_types() {} + + /** + * + */ + void run() { + status->episode_start( "third" ); + + status->eval_koan( *this, static_cast( &Koan02_character_types::lonely_characters ) ); + status->eval_koan( *this, static_cast( &Koan02_character_types::chars_have_a_size ) ); + status->eval_koan( *this, static_cast( &Koan02_character_types::chars_are_numbers ) ); + status->eval_koan( *this, static_cast( &Koan02_character_types::more_characters_are_strings ) ); + + status->episode_done( "third" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void lonely_characters(); + void chars_have_a_size(); + void chars_are_numbers(); + void more_characters_are_strings(); +}; + +#endif // KOAN02_CHARACTER_TYPES_HPP + +// EOF diff --git a/src/test/cpp/header/koan03_further_types.hpp b/src/test/cpp/header/koan03_further_types.hpp new file mode 100644 index 0000000..f04ed8b --- /dev/null +++ b/src/test/cpp/header/koan03_further_types.hpp @@ -0,0 +1,75 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN03_FURTHER_TYPES_HPP +#define KOAN03_FURTHER_TYPES_HPP + +class Koan03_further_types : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 1; //! + + public: + /** + * + */ + Koan03_further_types( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan03_further_types() {} + + /** + * + */ + void run() { + status->episode_start( "fourth" ); + + status->eval_koan( *this, static_cast( &Koan03_further_types::the_truth_has_a_name ) ); + + status->episode_done( "fourth" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void the_truth_has_a_name(); +}; + + +#endif // KOAN03_FURTHER_TYPES_HPP + +// EOF diff --git a/src/test/cpp/header/koan04_arrays.hpp b/src/test/cpp/header/koan04_arrays.hpp new file mode 100644 index 0000000..39c1364 --- /dev/null +++ b/src/test/cpp/header/koan04_arrays.hpp @@ -0,0 +1,76 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN04_ARRAYS_HPP +#define KOAN04_ARRAYS_HPP + +class Koan04_arrays : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 2; //! + + public: + /** + * + */ + Koan04_arrays( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan04_arrays() {} + + /** + * + */ + void run() { + status->episode_start( "fifth" ); + + status->eval_koan( *this, static_cast( &Koan04_arrays::listing_things ) ); + status->eval_koan( *this, static_cast( &Koan04_arrays::arrays_are_rigid ) ); + + status->episode_done( "fifth" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void listing_things(); + void arrays_are_rigid(); +}; + +#endif // KOAN04_ARRAYS_HPP + +// EOF diff --git a/src/test/cpp/header/koan05_pointers.hpp b/src/test/cpp/header/koan05_pointers.hpp new file mode 100644 index 0000000..360ed52 --- /dev/null +++ b/src/test/cpp/header/koan05_pointers.hpp @@ -0,0 +1,81 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +#ifndef KOAN05_POINTERS_HPP +#define KOAN05_POINTERS_HPP + +// Rename the Episode +class Koan05_pointers : Koan +{ + private: + KoanHandler *status; //! + static const int num_tests = 4; //! + + public: + /** + * + */ + Koan05_pointers( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~Koan05_pointers() {} + + /** + * + */ + void run() { + status->episode_start( "sixth" ); + + status->eval_koan( *this, static_cast( &Koan05_pointers::they_are_just_variables ) ); + status->eval_koan( *this, static_cast( &Koan05_pointers::they_are_really_just_variables ) ); + status->eval_koan( *this, static_cast( &Koan05_pointers::they_have_power ) ); + status->eval_koan( *this, static_cast( &Koan05_pointers::they_are_not_almighty ) ); + + status->episode_done( "sixth" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // REMARK: Do not forget to increase this.num_tests when you add another koan + void they_are_just_variables(); + void they_are_really_just_variables(); + void they_have_power(); + void they_are_not_almighty(); +}; + +#endif // KOAN05_POINTERS_HPP + +// EOF diff --git a/src/test/cpp/header/koanXX_sample_koans.hpp b/src/test/cpp/header/koanXX_sample_koans.hpp new file mode 100644 index 0000000..3ffc591 --- /dev/null +++ b/src/test/cpp/header/koanXX_sample_koans.hpp @@ -0,0 +1,80 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "../helper.hpp" + +// Do not to forget to rename the preprocessor directives as well! +#ifndef KOANXX_SAMPLE_KOANS_HPP +#define KOANXX_SAMPLE_KOANS_HPP + +// Rename the Episode +class KoanXX_sample_koans : Koan +{ + private: + KoanHandler *status; //! + // When ever a koan is added at the very bottom, this counter needs to be + // increased. + static const int num_tests = 1; //! + + public: + /** + * + */ + KoanXX_sample_koans( KoanHandler *status ) : status( status ) { + status->register_koans( num_tests ); + } + /** + * + */ + ~KoanXX_sample_koans() {} + + /** + * + */ + void run() { + // For each koan in this episode, one line needs to be written. + // The koans are executed in the order they are called here. + status->eval_koan( *this, static_cast( &KoanXX_sample_koans::a_sample_koan ) ); + + status->episode_done( "the-so-and-so'th" ); + } + + /** + * + */ + static int get_num_tests() { + return num_tests; + } + + private: + // Add further Koans down here by defining their name. + // The implementation of these is done in ~/koans/koanXX_sample_koans.cpp + // REMARK: Do not forget to increase this.num_tests when you add another koan + void a_sample_koan(); +}; + +#endif // KOANXX_SAMPLE_KOANS_HPP + +// EOF diff --git a/src/test/cpp/header/koan_handler.cpp b/src/test/cpp/header/koan_handler.cpp new file mode 100644 index 0000000..adf4055 --- /dev/null +++ b/src/test/cpp/header/koan_handler.cpp @@ -0,0 +1,101 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + + +#include "koan_handler.hpp" + +using namespace std; + +KoanHandler::KoanHandler() : total_num_koans( 0 ), total_num_passed( 0 ) +{ +} + +void KoanHandler::eval_koan( Koan obj, void ( Koan::*koan )() ) +{ + try { + ( obj.*koan )(); + this->total_num_passed++; + } catch( FillMeInException ex ) { + this->print_failure( ex ); + exit( 1 ); + } +} + +void KoanHandler::register_koans( int num_koans ) +{ + this->total_num_koans += num_koans; +} + +void KoanHandler::start() +{ + cout << "*******************************************************************************" + << endl + << "**** Welcome to CppKoans ****" + << endl + << "**** The master has " << this->total_num_koans + << " koans for you. ****" + << endl << endl; +} + +void KoanHandler::end() +{ + cout << "**** You've walked the path to enlightment and satisfied your master. ****" + << endl + << "*******************************************************************************" + << endl; +} + +void KoanHandler::episode_start( string order ) +{ + cout << "****\tThe " << order << " episode." << endl; +} + +void KoanHandler::episode_done( string order ) +{ + cout << "****\tCongratulations! You mastered the " << order << " episode." << endl + << "****\tDon't loose concentration. Keep going!" << endl + << endl; +} + +void KoanHandler::print_failure( FillMeInException ex ) +{ + if( !ex.msg.empty() ) { + cout << "Note:\t" << ex.msg << endl; + } + cout << "The master says, that you should meditate on '" << ex.file << ":" + << ex.line << "'." + << endl; + if( !ex.expect.empty() ) { + cout << "The master expected " << ex.expect << "." << endl; + } + cout << endl + << "**** You mastered " << this->total_num_passed << " of " + << this->total_num_koans << " koans. ****" + << endl + << "**** Keep going! ****" + << endl; +} + +// EOF diff --git a/src/test/cpp/header/koan_handler.hpp b/src/test/cpp/header/koan_handler.hpp new file mode 100644 index 0000000..6907235 --- /dev/null +++ b/src/test/cpp/header/koan_handler.hpp @@ -0,0 +1,90 @@ +/* + Copyright (c) 2012 Torbjörn Klatt + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef KOAN_HANDLER_HPP +#define KOAN_HANDLER_HPP + +#include +#include "fill_me_in_exception.hpp" +#include "koan.hpp" + +using namespace std; + +/** + * + */ +class KoanHandler +{ + private: + int total_num_koans; //! + int total_num_passed; //! + + public: + /** + * + */ + KoanHandler(); + + /** + * + */ + void eval_koan( Koan obj, void ( Koan::*koan )() ); + + /** + * + */ + void register_koans( int num_koans ); + + /** + * + */ + void start(); + + /** + * + */ + void end(); + + /** + * + */ + void episode_start( string order ); + + /** + * + */ + void episode_done( string order ); + + private: + /** + * + */ + void print_failure( FillMeInException ex ); +}; + +#endif // KOAN_HANDLER_HPP + +// EOF diff --git a/src/test/css/normalize.css b/src/test/css/normalize.css new file mode 100644 index 0000000..81c6f31 --- /dev/null +++ b/src/test/css/normalize.css @@ -0,0 +1,427 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} \ No newline at end of file diff --git a/src/test/css/skeleton.css b/src/test/css/skeleton.css new file mode 100644 index 0000000..f28bf6c --- /dev/null +++ b/src/test/css/skeleton.css @@ -0,0 +1,418 @@ +/* +* Skeleton V2.0.4 +* Copyright 2014, Dave Gamache +* www.getskeleton.com +* Free to use under the MIT license. +* http://www.opensource.org/licenses/mit-license.php +* 12/29/2014 +*/ + + +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #222; } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 2rem; + font-weight: 300; } +h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } +h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } +h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } +h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } + +/* Larger than phablet */ +@media (min-width: 550px) { + h1 { font-size: 5.0rem; } + h2 { font-size: 4.2rem; } + h3 { font-size: 3.6rem; } + h4 { font-size: 3.0rem; } + h5 { font-size: 2.4rem; } + h6 { font-size: 1.5rem; } +} + +p { + margin-top: 0; } + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; } +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; } +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: .5rem; + font-weight: 600; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Code +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +code { + padding: .2rem .5rem; + margin: 0 .2rem; + font-size: 90%; + white-space: nowrap; + background: #F1F1F1; + border: 1px solid #E1E1E1; + border-radius: 4px; } +pre > code { + display: block; + padding: 1rem 1.5rem; + white-space: pre; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 1rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 1.5rem; } +pre, +blockquote, +dl, +figure, +table, +p, +ul, +ol, +form { + margin-bottom: 2.5rem; } + + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} diff --git a/src/test/css/style.css b/src/test/css/style.css new file mode 100644 index 0000000..070ef71 --- /dev/null +++ b/src/test/css/style.css @@ -0,0 +1,201 @@ +html { + background-color: #0a0820; + font-size: 62.5%; + height: 100%; + width: 100%; +} + +@font-face { + font-family: "Signika"; + src: url(Signika-Regular.otf); +} +@font-face { + font-family: "League Gothic"; + src: url(LeagueGothic-Regular.otf); +} +body { + width: 100%; + height: 100%; +} + +.subheading { + text-align: center; +} + +.text, .secondheading, .subheading, #education { + color: white; +} + +.text { + font-size: 8rem; + font-family: "League Gothic"; +} + +.secondheading { + font-family: "Signika"; + font-size: 2rem; + opacity: .3; +} + +.subheading, #education { + font-family: "Signika"; + font-size: 3rem; + letter-spacing: 0.1rem; +} + +.body { + /*position: relative;*/ +} + +#education { + font-size: 2rem; + background-image: url(LowDefTelevision.jpg); +} + +.down-button { + margin: 0 39%; +} + +.work-container { + color: white; + display: inline-block; +} + +.work { + box-shadow: 10px 10px 5px black; + border-radius: 1rem; + background-color: #333; + display: inline-block; + padding: 1rem; + margin: 1rem; +} + +.work-title { + display: inline-block; + vertical-align: top; + padding-left: 5rem; + padding-top: 1.5rem; + margin-bottom: 0; +} + +.line-break { + margin: 1rem; + border-color: #d3d3d3; +} + +.legal { + position: absolute; + bottom: 0; + right: 0; + display: none; +} + +.work-header { + width: 100%; + text-align: center; +} + +.legal, .legal a { + color: #d3d3d3; +} + +video#bgvid { + position: fixed; + top: 50%; + left: 50%; + min-width: 100%; + min-height: 100%; + width: auto; + height: auto; + z-index: -100; + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + background: url(LowDefTelevision.jpg) no-repeat; + background-size: cover; +} + +@media (max-width: 321px) { + .right-align { + padding-right: 2.5rem; + text-align: right; + } + + .work-header { + margin: 12.5%; + display: block; + } + + .work-header-title { + text-align: center; + } + + .work { + margin: 0.5rem; + } + + .left-align { + padding-left: 2.5rem; + } + .secondheading { + letter-spacing: .6rem; + } + + .down-button { + margin-bottom: 2.5rem; + } + + .work { + width: 90%; + } +} + +@media (min-width: 321px) and (max-width: 420px) { + .right-align { + padding-left: 15rem; + } + .left-align { + padding-left: 5rem; + } + .secondheading { + letter-spacing: .85rem; + } + + .down-button { + margin: 0 45%; + } + +} + +@media (max-width: 420px) { + .container { + padding: 0; + width: 75%; + margin: 20% 12%; + } + + .desktopTitle { + display: none; + } +} + +@media (min-width:421px) { + .mobile_title { + display: none; + } + + .desktopTitle { + font-size: 25rem; + text-align: center; + } + + .secondheading { + padding-left: 2rem; + font-size: 6rem; + letter-spacing: 3rem; + text-align: center; + } + + .down-button { + display: none; + } +} \ No newline at end of file diff --git a/src/test/java/StudentNetworkSimulator.java b/src/test/java/StudentNetworkSimulator.java new file mode 100644 index 0000000..7e24670 --- /dev/null +++ b/src/test/java/StudentNetworkSimulator.java @@ -0,0 +1,248 @@ + +public class StudentNetworkSimulator extends NetworkSimulator { + /* + * Predefined Constants (static member variables): + * + * int MAXDATASIZE : the maximum size of the Message data and + * Packet payload + * + * int A : a predefined integer that represents entity A + * int B : a predefined integer that represents entity B + * + * + * Predefined Member Methods: + * + * void stopTimer(int entity): + * Stops the timer running at "entity" [A or B] + * void startTimer(int entity, double increment): + * Starts a timer running at "entity" [A or B], which will expire in + * "increment" time units, causing the interrupt handler to be + * called. You should only call this with A. + * void toLayer3(int callingEntity, Packet p) + * Puts the packet "p" into the network from "callingEntity" [A or B] + * void toLayer5(int entity, String dataSent) + * Passes "dataSent" up to layer 5 from "entity" [A or B] + * double getTime() + * Returns the current time in the simulator. Might be useful for + * debugging. + * void printEventList() + * Prints the current event list to stdout. Might be useful for + * debugging, but probably not. + * + * + * Predefined Classes: + * + * Message: Used to encapsulate a message coming from layer 5 + * Constructor: + * Message(String inputData): + * creates a new Message containing "inputData" + * Methods: + * boolean setData(String inputData): + * sets an existing Message's data to "inputData" + * returns true on success, false otherwise + * String getData(): + * returns the data contained in the message + * Packet: Used to encapsulate a packet + * Constructors: + * Packet (Packet p): + * creates a new Packet that is a copy of "p" + * Packet (int seq, int ack, int check, String newPayload) + * creates a new Packet with a sequence field of "seq", an + * ack field of "ack", a checksum field of "check", and a + * payload of "newPayload" + * Packet (int seq, int ack, int check) + * chreate a new Packet with a sequence field of "seq", an + * ack field of "ack", a checksum field of "check", and + * an empty payload + * Methods: + * boolean setSeqnum(int n) + * sets the Packet's sequence field to "n" + * returns true on success, false otherwise + * boolean setAcknum(int n) + * sets the Packet's ack field to "n" + * returns true on success, false otherwise + * boolean setChecksum(int n) + * sets the Packet's checksum to "n" + * returns true on success, false otherwise + * boolean setPayload(String newPayload) + * sets the Packet's payload to "newPayload" + * returns true on success, false otherwise + * int getSeqnum() + * returns the contents of the Packet's sequence field + * int getAcknum() + * returns the contents of the Packet's ack field + * int getChecksum() + * returns the checksum of the Packet + * String getPayload() + * returns the Packet's payload + * + */ + + // Add any necessary class variables here. Remember, you cannot use + // these variables to send messages error free! They can only hold + // state information for A or B. + // Also add any necessary methods (e.g. checksum of a String) + + // 'A' VARIABLES + int aSeqNum; + int aAckNum; + boolean packetSent; + boolean newPacket; + Packet packet; + + private int createChecksum(Packet packet) { + return packet.getSeqnum() + + packet.getAcknum() + + packet.getPayload().hashCode(); + } + + // This is the constructor. Don't touch! + public StudentNetworkSimulator(int numMessages, + double loss, + double corrupt, + double avgDelay, + int trace, + long seed) { + super(numMessages, loss, corrupt, avgDelay, trace, seed); + } + + // This routine will be called whenever the upper layer at the sender [A] + // has a message to send. It is the job of your protocol to insure that + // the data in such a message is delivered in-order, and correctly, to + // the receiving upper layer. Return 1 if accepting the message to send, + // return 0 if refusing to send the message + @Override + protected int aOutput(Message message) { + // Only create a packet if no packet is in transit, + // and the last packet has been sent successfully. + if (!packetSent && newPacket) { + // Packet creation + packet = new Packet(aSeqNum, aAckNum, 0, message.getData()); + packet.setChecksum(createChecksum(packet)); + debug("SENDING PACKETS"); + toLayer3(A, packet); + startTimer(A, 1000); + debug("NEW PACKET"); + packetSent = true; + newPacket = false; + return packetSent && !newPacket ? 1 : 0; + } else { + toLayer3(A, packet); + return 0; + } + } + + // This routine will be called whenever a packet sent from the B-side + // (i.e. as a result of a toLayer3() being done by a B-side procedure) + // arrives at the A-side. "packet" is the (possibly corrupted) packet + // sent from the B-side. + @Override + protected void aInput(Packet packet) { + //***GETTING STARTED*** + // This will be needed later, when dealing with acknowledgments sent from B + if (packet.getChecksum() == createChecksum(packet)) { + + if (packet.getSeqnum() == aSeqNum) { + stopTimer(A); + aSeqNum = packet.getAcknum(); + aAckNum = packet.getSeqnum() + 1; + packetSent = false; + newPacket = true; + } else { + packetSent = false; + } + } else { + packetSent = false; + } + } + + // This routine will be called when A's timer expires (thus generating a + // timer interrupt). You'll probably want to use this routine to control + // the retransmission of packets. See startTimer() and stopTimer(), above, + // for how the timer is started and stopped. + @Override + protected void aTimerInterrupt() { + //***GETTING STARTED*** + // This will be needed later, to deal with lost packets + debug("PACKET DROPPED SENDING ANOTHER"); + toLayer3(A, packet); + packetSent = true; + startTimer(A, 1000); + } + + // This routine will be called once, before any of your other A-side + // routines are called. It can be used to do any required + // initialization (e.g. of member variables you add to control the state + // of entity A). + @Override + protected void aInit() { + //***GETTING STARTED*** + // This will be needed later + aSeqNum = 0; + aAckNum = 0; + newPacket = true; + } + + // 'B' variables + Packet lastPacket; + String debugString; + // This routine will be called whenever a packet sent from the A-side + // (i.e. as a result of a toLayer3() being done by an A-side procedure) + // arrives at the B-side. "packet" is the (possibly corrupted) packet + // sent from the A-side. + @Override + protected void bInput(Packet packet) { + //***GETTING STARTED*** + // To get started, extract the payload from the packet + // and then send it up toLayer5 + + // To see reliability search for LETTERS line in the output.. + // It takes the first letter of each packet and adds them to a string. + // Example 26 Packets: abcdefghijklmnopqrstuvwxyz || abcdefghijklmnopqrstuvwxy + // As the program begins to shutdown once the last packet has been received + // And if the packet is corrupted or + // dropped the program will end before it can be resent. + if (packet.getChecksum() == createChecksum(packet)) { + + Packet ack = new Packet(packet.getAcknum(), packet.getSeqnum() + 1, 0, "ack"); + ack.setChecksum(createChecksum(ack)); + debug("SENDING ACKS"); + toLayer3(B, ack); + if (lastPacket == null) { + + toLayer5(B, packet.getPayload()); + lastPacket = packet; + debug("LETTERS: " + (debugString += packet.getPayload().substring(0, 1))); + } else if (!packet.getPayload().equals(lastPacket.getPayload())) { + lastPacket = packet; + toLayer5(B, packet.getPayload()); + debug("LETTERS: " + (debugString += packet.getPayload().substring(0, 1))); + } + } else { + + Packet nack = new Packet(packet.getAcknum() - 1, packet.getSeqnum(), 0, "nack"); + nack.setChecksum(createChecksum(nack)); + toLayer3(B, nack); + debug("SENDING NACKS"); + } + } + + // This routine will be called once, before any of your other B-side + // routines are called. It can be used to do any required + // initialization (e.g. of member variables you add to control the state + // of entity B). + @Override + protected void bInit() { + //***GETTING STARTED*** + // This will be needed later + lastPacket = null; + debugString = ""; + } + + private void debug(String message) { + + System.out.println("************************************"); + System.out.println(message); + System.out.println("************************************"); + } +} diff --git a/src/test/python_script.py b/src/test/python_script.py new file mode 100644 index 0000000..f37c3e5 --- /dev/null +++ b/src/test/python_script.py @@ -0,0 +1,21 @@ +from snake import * + +@key_map("c") +def toggle_snake_case_camel_case(): + """ toggles a word between snake case (some_function) and camelcase + (someFunction) """ + word = get_word() + + # it's snake case + if "_" in word: + chunks = word.split("_") + camel_case = chunks[0] + "".join([chunk.capitalize() for chunk in + chunks[1:]]) + replace_word(camel_case) + + # it's camel case + else: + # split our word on capital letters followed by non-capital letters + chunks = filter(None, re.split("([A-Z][^A-Z]*)", word)) + snake_case = "_".join([chunk.lower() for chunk in chunks]) + replace_word(snake_case) \ No newline at end of file