Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::io::{Read,BufRead,Write,stdin,stdout};
- #[derive(Debug)]
- struct Piece{
- value:i64,
- cumulative_value:i64,
- name:String,
- }
- #[derive(Debug)]
- struct Player{
- pieces:Vec<Piece>,
- name:String,
- value:i64,
- }
- fn read_confirm<R:BufRead>(read:&mut R)->bool{
- loop{
- print!("\naccept ? [y/n]:");
- stdout().flush().unwrap();
- match read_line(read).as_str(){
- "y"=>{return true;}
- "n"=>{return false;}
- _=>{}
- }
- }
- }
- fn read_num<R:BufRead>(read:&mut R)->i64{
- loop{
- if let Ok(result)=read_line(read).parse(){
- if result>=0 && result<(1<<62){
- return result;
- }
- }
- println!("not a valid number, try again");
- }
- }
- fn read_line<R:BufRead>(read:&mut R)->String{
- let mut string=String::new();
- read.read_line(&mut string).unwrap();
- string.trim().into()
- }
- fn read_player<R:BufRead>(read:&mut R)->Player{
- loop{
- print!("name: ");
- stdout().flush().unwrap();
- let name=read_line(read);
- print!("bonus: ");
- stdout().flush().unwrap();
- let bonus=read_num(read);
- print!("\n### piece list (descending importance) ###\nblank name to end list\n\n");
- let mut pieces=Vec::new();
- let mut total=0;
- loop{
- print!("name: ");
- stdout().flush().unwrap();
- let name=read_line(read);
- if name.is_empty(){
- break;
- }
- print!("value: ");
- stdout().flush().unwrap();
- let value=read_num(read);
- total+=value;
- pieces.push(Piece{name,value,cumulative_value:total});
- }
- let value=pieces.iter().map(|p|p.value).sum::<i64>()+bonus;
- let player=Player{pieces,name,value};
- player.print();
- if read_confirm(read){
- return player;
- }
- }
- }
- impl Player{
- fn print(&self){
- print!("\n### player data ###\n\n");
- print!("name: {:?}\nvalue:{}\npieces:\n",self.name,self.value);
- print!("\t{:^30}|{:^10}|{:^20}|{:^20}|active\n","name","value","cumulative value","lose after");
- for p in &self.pieces{
- let diff=self.value-p.cumulative_value;
- print!("\t{:30}|{:10}|{:20}|{:20}|{}\n",p.name,p.value,p.cumulative_value,diff,diff>=0);
- }
- }
- fn find_end_of_active(&self)->usize{
- self.pieces.iter().position(|p|p.cumulative_value< self.value).unwrap_or(self.pieces.len())
- }
- fn remove_value_print(&mut self,v:i64){
- let pre_pos=self.find_end_of_active();
- self.value-=v;
- let post_pos=self.find_end_of_active();
- let removed:Vec<&String>=self.pieces[post_pos..pre_pos].iter().map(|p|&p.name).collect();
- if removed.is_empty(){
- return;
- }
- print!("player {}:\n",self.name);
- for p in &removed{
- print!("\tremove {}\n",p);
- }
- }
- fn add_value_print(&mut self,v:i64){
- let pre_pos=self.find_end_of_active();
- self.value+=v;
- let post_pos=self.find_end_of_active();
- let added:Vec<&String>=self.pieces[pre_pos..post_pos].iter().map(|p|&p.name).collect();
- if added.is_empty(){
- return;
- }
- print!("player {}:\n",self.name);
- for p in &added{
- print!("\tadd {}\n",p);
- }
- }
- }
- fn parse_num_word(word:Option<&str>,max:usize)->Option<usize>{
- if let Some(word)=word{
- if let Ok(num)=word.parse::<usize>(){
- if num<max{
- return Some(num);
- }
- }
- }
- None
- }
- fn read_transacion<R:BufRead>(players:&mut [Player],read:&mut R){
- print!("transfer to: ");
- let to=read_player_id(players,read);
- let mut total=0;
- let mut transactions=Vec::new();
- loop{
- print!("transfer from player (blank to end):");
- stdout().flush().unwrap();
- if let Some(id)=read_player_optional(players,read){
- print!("transfer value: ");
- stdout().flush().unwrap();
- let value=read_num(read);
- total+=value;
- transactions.push((id,value));
- }else{
- break;
- }
- }
- print!("confirm transactions");
- for p in &transactions{
- print!("{:30}|{}\n",players[p.0].name,p.1);
- }
- println!("-> {:27}|{}",players[to].name,total);
- if read_confirm(read){
- players[to].add_value_print(total);
- for p in &transactions{
- players[p.0].remove_value_print(p.1);
- }
- }
- }
- fn read_player_id<R:BufRead>(players:&[Player],read:&mut R)->usize{
- loop{
- if let Some(p)=read_player_optional(players,read){
- return p;
- }
- }
- }
- fn read_player_optional<R:BufRead>(players:&[Player],read:&mut R)->Option<usize>{
- loop{
- let line=read_line(read);
- if line.is_empty(){
- return None;
- }
- if let Ok(id)=line.parse::<usize>(){
- if id <players.len(){
- return Some(id);
- }else{
- println!("invalid player id try again");
- print_player_list(players);
- }
- }else{
- println!("not a number, try again");
- }
- }
- }
- fn print_player_list(players:&[Player]){
- for i in 0..players.len(){
- println!("{:3}|{}",i,players[i].name);
- }
- }
- fn main(){
- let stdin=stdin();
- let mut stdin=stdin.lock();
- print!("number of players: ");
- stdout().flush().unwrap();
- let player_count=read_num(&mut stdin);
- assert!(player_count>=2);
- let mut players=Vec::new();
- for _ in 0..player_count{
- players.push(read_player(&mut stdin));
- }
- loop{
- let line=read_line(&mut stdin);
- let mut words=line.split_whitespace();
- match words.next(){
- Some("p")|Some("print")=>{
- if let Some(id)=parse_num_word(words.next(),players.len()){
- players[id].print();
- }else{
- println!("invalid player id");
- }
- },
- Some("l")|Some("list")=>{
- print_player_list(&players);
- },
- Some("t")|Some("transfer")=>{
- read_transacion(&mut players,&mut stdin)
- },
- None|Some("")=>{},
- Some(_)=>println!("invalid command"),
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement