Skip to content

tournament: Put inputs/expectations inline, not in files #152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"roman-numerals",
"hexadecimal",
"grade-school",
"tournament",
"robot-simulator",
"queen-attack",
"sublist",
Expand All @@ -35,7 +36,6 @@
"minesweeper",
"dominoes",
"parallel-letter-frequency",
"tournament",
"rectangles",
"forth",
"circular-buffer"
Expand Down
31 changes: 10 additions & 21 deletions exercises/tournament/example.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use std::cmp::Ordering::Equal;
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Write, Result};
use std::path::Path;

enum GameResult {
Win,
Expand All @@ -29,12 +26,9 @@ impl TeamResult {
}
}

pub fn tally(input_filename: &Path, output_filename: &Path) -> Result<u32> {
let reader = BufReader::with_capacity(2048, File::open(input_filename).unwrap());
let mut count = 0;
pub fn tally(input: &str) -> String {
Copy link
Member Author

@petertseng petertseng Jul 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like a reminder on the idiomatic-ness of str and String. I will see if I can find an answer myself.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html argues for using &str as argument. I will keep that.

On the other hand String makes the most sense for what I output since I'm concatenating in write_tally

let mut results: HashMap<String, TeamResult> = HashMap::new();
for line in reader.lines() {
let line = line.unwrap();
for line in input.to_string().lines() {
let parts: Vec<&str> = line.trim_right().split(';').collect();
if parts.len() != 3 { continue; }
let team1 = parts[0];
Expand All @@ -44,26 +38,22 @@ pub fn tally(input_filename: &Path, output_filename: &Path) -> Result<u32> {
"win" => {
add_game_result(&mut results, team1.to_string(), GameResult::Win);
add_game_result(&mut results, team2.to_string(), GameResult::Loss);
count += 1;
},
"draw" => {
add_game_result(&mut results, team1.to_string(), GameResult::Draw);
add_game_result(&mut results, team2.to_string(), GameResult::Draw);
count += 1;
},
"loss" => {
add_game_result(&mut results, team1.to_string(), GameResult::Loss);
add_game_result(&mut results, team2.to_string(), GameResult::Win);
count += 1;
},
_ => () // Ignore bad lines
}
}
try!(write_tally(&results, output_filename));
Ok(count)
write_tally(&results)
}

fn write_tally(results: &HashMap<String, TeamResult>, output_filename: &Path) -> Result<()> {
fn write_tally(results: &HashMap<String, TeamResult>) -> String {
let mut v: Vec<_> = results.iter().map(|(team, r)| {
let games = r.wins + r.draws + r.losses;
let points = r.wins * 3 + r.draws;
Expand All @@ -75,13 +65,12 @@ fn write_tally(results: &HashMap<String, TeamResult>, output_filename: &Path) ->
Equal => a.1.cmp(&(b.1)).reverse(),
other => other
});
let mut f = try!(File::create(output_filename));
try!(writeln!(&mut f, "{:30} | MP | W | D | L | P", "Team"));
for &(ref team, games, r, points) in v.iter() {
try!(writeln!(&mut f, "{:30} | {:2} | {:2} | {:2} | {:2} | {:2}",
team, games, r.wins, r.draws, r.losses, points));
}
Ok(())
let header = format!("{:30} | MP | W | D | L | P\n", "Team");
let lines: Vec<_> = v.iter().map(|&(ref team, games, r, points)| {
format!("{:30} | {:2} | {:2} | {:2} | {:2} | {:2}",
team, games, r.wins, r.draws, r.losses, points)
}).collect();
header + &lines.join("\n")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that for an empty input, this prints the header and nothing after. No test tests this behavior, so I have nothing to say about whether this appropriate.

}

fn add_game_result(results: &mut HashMap<String, TeamResult>, team: String, result: GameResult) {
Expand Down
5 changes: 0 additions & 5 deletions exercises/tournament/tests/expected1.txt

This file was deleted.

5 changes: 0 additions & 5 deletions exercises/tournament/tests/expected2.txt

This file was deleted.

5 changes: 0 additions & 5 deletions exercises/tournament/tests/expected3.txt

This file was deleted.

6 changes: 0 additions & 6 deletions exercises/tournament/tests/input1.txt

This file was deleted.

11 changes: 0 additions & 11 deletions exercises/tournament/tests/input2.txt

This file was deleted.

4 changes: 0 additions & 4 deletions exercises/tournament/tests/input3.txt

This file was deleted.

78 changes: 42 additions & 36 deletions exercises/tournament/tests/tournament.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,57 @@
use std::fs::File;
use std::path::Path;
use std::io::Read;

extern crate tournament;

fn file_equal(output_file: &str, expected_file: &str) {
let output = match File::open(&Path::new(output_file)) {
Err(e) => panic!("Couldn't open {}: {}", output_file, e),
Ok(mut f) => {
let mut buf = String::new();
match f.read_to_string(&mut buf) {
Err(e) => panic!("Couldn't read {}: {}", output_file, e),
Ok(_) => buf
}
}
};
let expected = match File::open(&Path::new(expected_file)) {
Err(e) => panic!("Couldn't open {}: {}", expected_file, e),
Ok(mut f) => {
let mut buf = String::new();
match f.read_to_string(&mut buf) {
Err(e) => panic!("Couldn't read {}: {}", expected_file, e),
Ok(_) => buf
}
}
};
assert_eq!("\n".to_string() + output.as_ref(), "\n".to_string() + expected.as_ref());

}


#[test]
fn test_good() {
assert_eq!(tournament::tally(&Path::new("tests/input1.txt"), &Path::new("tests/output1.txt")).unwrap(), 6);
file_equal("tests/output1.txt", "tests/expected1.txt");
let input = "Allegoric Alaskians;Blithering Badgers;win\n".to_string() +
"Devastating Donkeys;Courageous Californians;draw\n" +
"Devastating Donkeys;Allegoric Alaskians;win\n" +
"Courageous Californians;Blithering Badgers;loss\n" +
"Blithering Badgers;Devastating Donkeys;loss\n" +
"Allegoric Alaskians;Courageous Californians;win";
let expected = "Team | MP | W | D | L | P\n".to_string() +
"Devastating Donkeys | 3 | 2 | 1 | 0 | 7\n" +
"Allegoric Alaskians | 3 | 2 | 0 | 1 | 6\n" +
"Blithering Badgers | 3 | 1 | 0 | 2 | 3\n" +
"Courageous Californians | 3 | 0 | 1 | 2 | 1";

assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn test_ignore_bad_lines() {
assert_eq!(tournament::tally(&Path::new("tests/input2.txt"), &Path::new("tests/output2.txt")).unwrap(), 6);
file_equal("tests/output2.txt", "tests/expected2.txt");
let input = "Allegoric Alaskians;Blithering Badgers;win\n".to_string() +
"Devastating Donkeys_Courageous Californians;draw\n" +
"Devastating Donkeys;Allegoric Alaskians;win\n" +
"\n" +
"Courageous Californians;Blithering Badgers;loss\n" +
"Bla;Bla;Bla\n" +
"Blithering Badgers;Devastating Donkeys;loss\n" +
"# Yackity yackity yack\n" +
"Allegoric Alaskians;Courageous Californians;win\n" +
"Devastating Donkeys;Courageous Californians;draw\n" +
"Devastating Donkeys@Courageous Californians;draw";
let expected = "Team | MP | W | D | L | P\n".to_string() +
"Devastating Donkeys | 3 | 2 | 1 | 0 | 7\n" +
"Allegoric Alaskians | 3 | 2 | 0 | 1 | 6\n" +
"Blithering Badgers | 3 | 1 | 0 | 2 | 3\n" +
"Courageous Californians | 3 | 0 | 1 | 2 | 1";

assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn test_incomplete_competition() {
assert_eq!(tournament::tally(&Path::new("tests/input3.txt"), &Path::new("tests/output3.txt")).unwrap(), 4);
file_equal("tests/output3.txt", "tests/expected3.txt");
let input = "Allegoric Alaskians;Blithering Badgers;win\n".to_string() +
"Devastating Donkeys;Allegoric Alaskians;win\n" +
"Courageous Californians;Blithering Badgers;loss\n" +
"Allegoric Alaskians;Courageous Californians;win";
let expected = "Team | MP | W | D | L | P\n".to_string() +
"Allegoric Alaskians | 3 | 2 | 0 | 1 | 6\n" +
"Blithering Badgers | 2 | 1 | 0 | 1 | 3\n" +
"Devastating Donkeys | 1 | 1 | 0 | 0 | 3\n" +
"Courageous Californians | 2 | 0 | 0 | 2 | 0";

assert_eq!(tournament::tally(&input), expected);
}