clordle 0.1.0

A fun command-line Wordle clone written in Rust.

use std::fs::read_to_string;
use std::io::stdout;
use std::string::String;
use chrono::prelude::*;
use clap::{Parser, Subcommand};
use colored::Colorize;
use text_io::read;
use rand::{rng, Rng};
use reqwest::get;
use serde_json::{from_str, Value};
const WORDLIST: &str = include_str!("valid-wordle-words.txt");


#[derive(Parser)]
struct Cli {
    #[command(subcommand)]
    command: Option<Commands>
}

///Play a cli version of the popular game wordle
#[derive(Subcommand)]
enum Commands{

    ///daily wordle challenge
    daily{

    },
    ///choose a random word to play
    random{

    }
}

#[tokio::main]
async fn main()  {
    let cli = Cli::parse();

    let mut solution = "";
    let word_today = get_word_today().await;
    let word_list = WORDLIST;

    let words: Vec<&str> = word_list.lines().collect();
    let word_amount = words.len();

    let mut rng = rand::thread_rng();
    let word = words[rng.gen_range(0..word_amount)].to_string();

    let _ = &match &cli.command {
        Some(Commands::daily {}) => {
            solution = word_today.as_str();
        },
        Some(Commands::random {}) => {
            solution = &word
        },
        None => {
            solution = word_today.as_str();
        }
    };

    main_game_loop(solution, &word_list);
}

fn get_word_list() -> String {

    let words = read_to_string("src/valid-wordle-words.txt")
    .unwrap();

    return(words);
    
}

async fn get_word_today() ->  String {
    let date: &str = &Utc::now().with_timezone(&FixedOffset::west_opt(5 * 3600).unwrap()).to_string()[..10];
    let url = format!("https://www.nytimes.com/svc/wordle/v2/{}.json", date);
    let resp = get(url).await.expect("REASON").text().await;

    let solution: Value = from_str(&*resp.unwrap().to_string()).expect("REASON");

    return solution["solution"].as_str().unwrap().parse().unwrap();
}



fn main_game_loop(solution: &str, word_list: &str ){

    let mut n = 0;
    let mut won = false;
    while (n < 5) {
        let mut word: String = read!( "{}");
        let mut wrong_order: Vec<char> = vec![];
        let mut correct: Vec<char> = vec![];
        let mut wrong: Vec<char> = vec![];

        let mut is_length : bool = false;
        let mut is_valid: bool = false;

        let mut error_msg = "";
        word = word.to_lowercase();


        if(!word_list.contains(&word)) {
            error_msg ="Word is not in word list";
        }
        else{
            is_valid = true;
        }

        if (word.chars().count() != 5){
            error_msg = "Word is not 5 characters long ";
        }
        else{
            is_length = true;
        }


        if (is_length && is_valid) {
            n += 1;
            print!("\x1B[1A\x1B[2K");
            for (i, c) in word.char_indices() {
                if solution.find(c) != None {
                    if solution.chars().nth(i).unwrap() == c {
                        print!("{}", c.to_string().green().bold());
                        correct.push(c);
                    } else {
                        print!("{}", c.to_string().yellow().bold());
                        wrong_order.push(c);
                    }
                } else {
                    print!("{}", c.to_string().red().bold());
                    wrong.push(c);
                }
            }
            let correct_string: String = correct.into_iter().collect();
            let wrong_order_string: String = wrong_order.into_iter().collect();
            let wrong_string: String = wrong.into_iter().collect();

            if (wrong_string == "" && wrong_order_string== ""){
                won = true;
                break;

            }
        }
        else {
            println!("{}", error_msg);
        }
        println!("\n");
    }
    if(won){
        println!("Congratulations on winning")
    }
    println!("{}", solution)

}