cch23_validator/
lib.rs

1pub mod args;
2
3use std::{ops::Deref, sync::Arc};
4
5use base64::{engine::general_purpose, Engine};
6use futures_util::{
7    stream::{SplitSink, SplitStream},
8    SinkExt, StreamExt,
9};
10use reqwest::{
11    header::{HeaderValue, CONTENT_TYPE},
12    multipart::{Form, Part},
13    redirect::Policy,
14    StatusCode,
15};
16pub use shuttlings;
17use shuttlings::{SubmissionState, SubmissionUpdate};
18use tokio::{
19    net::TcpStream,
20    sync::mpsc::Sender,
21    time::{sleep, Duration},
22};
23use tokio_tungstenite::{tungstenite::Message, MaybeTlsStream, WebSocketStream};
24use tracing::info;
25use uuid::Uuid;
26
27pub const SUPPORTED_CHALLENGES: &[i32] =
28    &[-1, 1, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 18, 19, 20, 21, 22];
29pub const SUBMISSION_TIMEOUT: u64 = 60;
30
31pub async fn run(url: String, id: Uuid, number: i32, tx: Sender<SubmissionUpdate>) {
32    info!(%id, %url, %number, "Starting submission");
33
34    tx.send(SubmissionState::Running.into()).await.unwrap();
35    tx.send(SubmissionUpdate::Save).await.unwrap();
36
37    tokio::select! {
38        _ = validate(url.as_str(), number, tx.clone()) => (),
39        _ = sleep(Duration::from_secs(SUBMISSION_TIMEOUT)) => {
40            // if the validation task timed out
41            info!(%id, %url, %number, "Submission timed out");
42            tx.send("Timed out".to_owned().into()).await.unwrap();
43            tx.send(SubmissionState::Done.into()).await.unwrap();
44            tx.send(SubmissionUpdate::Save).await.unwrap();
45        },
46    };
47    info!(%id, %url, %number, "Completed submission");
48}
49
50/// Task number and Test number in the current challenge
51type TaskTest = (i32, i32);
52/// If failure, return tuple with task number and test number that failed
53type ValidateResult = std::result::Result<(), TaskTest>;
54
55pub async fn validate(url: &str, number: i32, tx: Sender<SubmissionUpdate>) {
56    if !SUPPORTED_CHALLENGES.contains(&number) {
57        tx.send(
58            format!("Validating Challenge {number} is not supported yet! Check for updates.")
59                .into(),
60        )
61        .await
62        .unwrap();
63        return;
64    }
65    let txc = tx.clone();
66    if let Err((task, test)) = match number {
67        -1 => validate_minus1(url, txc).await,
68        1 => validate_1(url, txc).await,
69        4 => validate_4(url, txc).await,
70        5 => validate_5(url, txc).await,
71        6 => validate_6(url, txc).await,
72        7 => validate_7(url, txc).await,
73        8 => validate_8(url, txc).await,
74        11 => validate_11(url, txc).await,
75        12 => validate_12(url, txc).await,
76        13 => validate_13(url, txc).await,
77        14 => validate_14(url, txc).await,
78        15 => validate_15(url, txc).await,
79        18 => validate_18(url, txc).await,
80        19 => validate_19(url, txc).await,
81        20 => validate_20(url, txc).await,
82        21 => validate_21(url, txc).await,
83        22 => validate_22(url, txc).await,
84        _ => unreachable!(),
85    } {
86        info!(%url, %number, %task, %test, "Submission failed");
87        tx.send(format!("Task {task}: test #{test} failed 🟥").into())
88            .await
89            .unwrap();
90    }
91    tx.send(SubmissionState::Done.into()).await.unwrap();
92    tx.send(SubmissionUpdate::Save).await.unwrap();
93}
94
95fn new_client() -> reqwest::Client {
96    reqwest::ClientBuilder::new()
97        .http1_only()
98        .connect_timeout(Duration::from_secs(3))
99        .redirect(Policy::limited(3))
100        .referer(false)
101        .timeout(Duration::from_secs(60))
102        .build()
103        .unwrap()
104}
105
106async fn validate_minus1(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
107    let client = new_client();
108    let mut test: TaskTest;
109    // TASK 1: respond 200
110    test = (1, 1);
111    let url = &format!("{}/", base_url);
112    let res = client.get(url).send().await.map_err(|_| test)?;
113    if res.status() != StatusCode::OK {
114        return Err(test);
115    }
116    // TASK 1 DONE
117    tx.send((true, 0).into()).await.unwrap();
118    tx.send(SubmissionUpdate::Save).await.unwrap();
119
120    // TASK 2: respond 500
121    test = (2, 1);
122    let url = &format!("{}/-1/error", base_url);
123    let res = client.get(url).send().await.map_err(|_| test)?;
124    if res.status() != StatusCode::INTERNAL_SERVER_ERROR {
125        return Err(test);
126    }
127    // TASK 2 DONE
128    tx.send((false, 0).into()).await.unwrap();
129
130    Ok(())
131}
132
133async fn validate_1(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
134    let client = new_client();
135    let mut test: TaskTest;
136    // TASK 1: basic formula
137    test = (1, 1);
138    let url = &format!("{}/1/2/3", base_url);
139    let res = client.get(url).send().await.map_err(|_| test)?;
140    let text = res.text().await.map_err(|_| test)?;
141    if text != "1" {
142        return Err(test);
143    }
144    test = (1, 2);
145    let url = &format!("{}/1/12/16", base_url);
146    let res = client.get(url).send().await.map_err(|_| test)?;
147    let text = res.text().await.map_err(|_| test)?;
148    if text != "21952" {
149        return Err(test);
150    }
151    // TASK 1 DONE
152    tx.send((true, 0).into()).await.unwrap();
153    tx.send(SubmissionUpdate::Save).await.unwrap();
154
155    // TASK 2: multiple and zero and negative numbers
156    test = (2, 1);
157    let url = &format!("{}/1/3/5/7/9", base_url);
158    let res = client.get(url).send().await.map_err(|_| test)?;
159    let text = res.text().await.map_err(|_| test)?;
160    if text != "512" {
161        return Err(test);
162    }
163    test = (2, 2);
164    let url = &format!("{}/1/0/0/0", base_url);
165    let res = client.get(url).send().await.map_err(|_| test)?;
166    let text = res.text().await.map_err(|_| test)?;
167    if text != "0" {
168        return Err(test);
169    }
170    test = (2, 3);
171    let url = &format!("{}/1/-3/1", base_url);
172    let res = client.get(url).send().await.map_err(|_| test)?;
173    let text = res.text().await.map_err(|_| test)?;
174    if text != "-64" {
175        return Err(test);
176    }
177    test = (2, 4);
178    let url = &format!("{}/1/3/5/7/9/2/13/12/16/18", base_url);
179    let res = client.get(url).send().await.map_err(|_| test)?;
180    let text = res.text().await.map_err(|_| test)?;
181    if text != "729" {
182        return Err(test);
183    }
184    tx.send((false, 100).into()).await.unwrap();
185
186    Ok(())
187}
188
189async fn validate_4(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
190    let client = new_client();
191    let mut test: TaskTest;
192    // TASK 1
193    test = (1, 1);
194    let url = &format!("{}/4/strength", base_url);
195    let res = client
196        .post(url)
197        .json(&serde_json::json!([
198            {
199              "name": "Zeus",
200              "strength": 8
201            },
202            {
203              "name": "Oner",
204              "strength": 6
205            },
206            {
207              "name": "Faker",
208              "strength": 7
209            },
210            {
211              "name": "Gumayusi",
212              "strength": 6
213            },
214            {
215              "name": "Keria",
216              "strength": 6
217            }
218        ]))
219        .send()
220        .await
221        .map_err(|_| test)?;
222    let text = res.text().await.map_err(|_| test)?;
223    if text != "33" {
224        return Err(test);
225    }
226    // TASK 1 DONE
227    tx.send((true, 0).into()).await.unwrap();
228    tx.send(SubmissionUpdate::Save).await.unwrap();
229
230    // TASK 2
231    test = (2, 1);
232    let url = &format!("{}/4/contest", base_url);
233    let res = client
234        .post(url)
235        .json(&serde_json::json!([
236        {
237            "name": "Zeus",
238            "strength": 8,
239            "speed": 51.2,
240            "height": 81,
241            "antler_width": 31,
242            "snow_magic_power": 311,
243            "favorite_food": "pizza",
244            "cAnD13s_3ATeN-yesT3rdAy": 4
245        },
246        {
247            "name": "Oner",
248            "strength": 6,
249            "speed": 41.3,
250            "height": 51,
251            "antler_width": 30,
252            "snow_magic_power": 321,
253            "favorite_food": "burger",
254            "cAnD13s_3ATeN-yesT3rdAy": 1
255        },
256        {
257            "name": "Faker",
258            "strength": 7,
259            "speed": 50,
260            "height": 50,
261            "antler_width": 37,
262            "snow_magic_power": 6667,
263            "favorite_food": "broccoli",
264            "cAnD13s_3ATeN-yesT3rdAy": 1
265        },
266        {
267            "name": "Gumayusi",
268            "strength": 6,
269            "speed": 60.1,
270            "height": 50,
271            "antler_width": 34,
272            "snow_magic_power": 2323,
273            "favorite_food": "pizza",
274            "cAnD13s_3ATeN-yesT3rdAy": 1
275        },
276        {
277            "name": "Keria",
278            "strength": 6,
279            "speed": 48.2,
280            "height": 65,
281            "antler_width": 33,
282            "snow_magic_power": 5014,
283            "favorite_food": "wok",
284            "cAnD13s_3ATeN-yesT3rdAy": 5
285        }
286        ]))
287        .send()
288        .await
289        .map_err(|_| test)?;
290    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
291    if json
292        != serde_json::json!({
293            "fastest":"Speeding past the finish line with a strength of 6 is Gumayusi",
294            "tallest":"Zeus is standing tall with his 31 cm wide antlers",
295            "magician":"Faker could blast you away with a snow magic power of 6667",
296            "consumer":"Keria ate lots of candies, but also some wok"
297        })
298    {
299        return Err(test);
300    }
301    tx.send((false, 150).into()).await.unwrap();
302
303    Ok(())
304}
305
306async fn validate_5(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
307    // TASK 1
308    let t = JSONTester::new(format!("{}/5?offset=0&limit=8", base_url));
309    t.test(
310        (1, 1),
311        &serde_json::json!(["Ava", "Caleb", "Mia", "Owen", "Lily", "Ethan", "Zoe", "Nolan"]),
312        StatusCode::OK,
313        &serde_json::json!(["Ava", "Caleb", "Mia", "Owen", "Lily", "Ethan", "Zoe", "Nolan"]),
314    )
315    .await?;
316    let t = JSONTester::new(format!("{}/5?offset=10&limit=4", base_url));
317    t.test(
318        (1, 2),
319        &serde_json::json!([
320            "Ava", "Caleb", "Mia", "Owen", "Lily", "Ethan", "Zoe", "Nolan", "Harper", "Lucas",
321            "Stella", "Mason", "Olivia", "Wyatt", "Isabella", "Logan",
322        ]),
323        StatusCode::OK,
324        &serde_json::json!(["Stella", "Mason", "Olivia", "Wyatt"]),
325    )
326    .await?;
327    // TASK 1 DONE
328    tx.send((true, 0).into()).await.unwrap();
329    tx.send(SubmissionUpdate::Save).await.unwrap();
330
331    // TASK 2
332    let t = JSONTester::new(format!("{}/5?offset=0&limit=5", base_url));
333    t.test(
334        (2, 1),
335        &serde_json::json!([]),
336        StatusCode::OK,
337        &serde_json::json!([]),
338    )
339    .await?;
340    let t = JSONTester::new(format!("{}/5", base_url));
341    t.test(
342        (2, 2),
343        &serde_json::json!(["Alice", "Bob", "Charlie", "David"]),
344        StatusCode::OK,
345        &serde_json::json!(["Alice", "Bob", "Charlie", "David"]),
346    )
347    .await?;
348    let t = JSONTester::new(format!("{}/5?offset=2", base_url));
349    t.test(
350        (2, 3),
351        &serde_json::json!(["Alice", "Bob", "Charlie", "David"]),
352        StatusCode::OK,
353        &serde_json::json!(["Charlie", "David"]),
354    )
355    .await?;
356    let t = JSONTester::new(format!("{}/5?offset=2&limit=0", base_url));
357    t.test(
358        (2, 4),
359        &serde_json::json!(["Alice", "Bob", "Charlie", "David"]),
360        StatusCode::OK,
361        &serde_json::json!([]),
362    )
363    .await?;
364    let t = JSONTester::new(format!("{}/5?split=6", base_url));
365    t.test(
366        (2, 5),
367        &serde_json::json!([
368            "Alice", "Bob", "Charlie", "David", "Eva", "Frank", "Grace", "Hank", "Ivy", "Jack",
369            "Katie", "Liam", "Mia", "Nathan", "Olivia", "Paul", "Quinn", "Rachel", "Samuel",
370            "Tara", "Aria", "Jackson"
371        ]),
372        StatusCode::OK,
373        &serde_json::json!([
374            ["Alice", "Bob", "Charlie", "David", "Eva", "Frank"],
375            ["Grace", "Hank", "Ivy", "Jack", "Katie", "Liam"],
376            ["Mia", "Nathan", "Olivia", "Paul", "Quinn", "Rachel"],
377            ["Samuel", "Tara", "Aria", "Jackson"]
378        ]),
379    )
380    .await?;
381    let t = JSONTester::new(format!("{}/5?offset=2&limit=4&split=1", base_url));
382    t.test(
383        (2, 6),
384        &serde_json::json!([
385            "Alice", "Bob", "Charlie", "David", "Alice", "Bob", "Charlie", "David"
386        ]),
387        StatusCode::OK,
388        &serde_json::json!([["Charlie"], ["David"], ["Alice"], ["Bob"],]),
389    )
390    .await?;
391    let t = JSONTester::new(format!("{}/5?limit=0", base_url));
392    t.test(
393        (2, 7),
394        &serde_json::json!(["Alice", "Bob", "Charlie", "David"]),
395        StatusCode::OK,
396        &serde_json::json!([]),
397    )
398    .await?;
399    let t = JSONTester::new(format!("{}/5?offset=0&limit=0", base_url));
400    t.test(
401        (2, 8),
402        &serde_json::json!(["Alice", "Bob", "Charlie", "David"]),
403        StatusCode::OK,
404        &serde_json::json!([]),
405    )
406    .await?;
407    tx.send((false, 150).into()).await.unwrap();
408
409    Ok(())
410}
411
412async fn validate_6(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
413    let client = new_client();
414    let mut test: TaskTest;
415    let url = &format!("{}/6", base_url);
416    // TASK 1: elf
417    test = (1, 1);
418    let res = client
419        .post(url)
420        .body("elf elf elf")
421        .send()
422        .await
423        .map_err(|_| test)?;
424    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
425    if json["elf"] != serde_json::Value::Number(3.into()) {
426        return Err(test);
427    }
428    test = (1, 2);
429    let res = client
430        .post(url)
431        .body("In the quirky town of Elf stood an enchanting shop named 'The Elf & Shelf.' Managed by Wally, a mischievous elf with a knack for crafting exquisite shelves, the shop was a bustling hub of elf after elf who wanter to see their dear elf in Belfast.")
432        .send()
433        .await
434        .map_err(|_| test)?;
435    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
436    if json["elf"] != serde_json::Value::Number(6.into()) {
437        return Err(test);
438    }
439    // TASK 1 DONE
440    tx.send((true, 0).into()).await.unwrap();
441    tx.send(SubmissionUpdate::Save).await.unwrap();
442
443    // TASK 2: more strings
444    test = (2, 1);
445    let res = client
446        .post(url)
447        .body("elf elf elf on a shelf")
448        .send()
449        .await
450        .map_err(|_| test)?;
451    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
452    if json
453        != serde_json::json!({
454            "elf":4,
455            "elf on a shelf":1,
456            "shelf with no elf on it":0
457        })
458    {
459        return Err(test);
460    }
461    test = (2, 2);
462    let res = client
463        .post(url)
464        .body("In Belfast I heard an elf on a shelf on a shelf on a ")
465        .send()
466        .await
467        .map_err(|_| test)?;
468    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
469    if json
470        != serde_json::json!({
471            "elf":4,
472            "elf on a shelf":2,
473            "shelf with no elf on it":0
474        })
475    {
476        return Err(test);
477    }
478    test = (2, 3);
479    let res = client
480        .post(url)
481        .body("Somewhere in Belfast under a shelf store but above the shelf realm there's an elf on a shelf on a shelf on a shelf on a elf on a shelf on a shelf on a shelf on a shelf on a elf on a elf on a elf on a shelf on a ")
482        .send()
483        .await
484        .map_err(|_| test)?;
485    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
486    if json
487        != serde_json::json!({
488            "elf":16,
489            "elf on a shelf":8,
490            "shelf with no elf on it":2
491        })
492    {
493        return Err(test);
494    }
495    // TASK 2 DONE
496    tx.send((false, 200).into()).await.unwrap();
497
498    Ok(())
499}
500
501async fn validate_7(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
502    let client = new_client();
503    let mut test: TaskTest;
504    // TASK 1
505    test = (1, 1);
506    let url = &format!("{}/7/decode", base_url);
507    let data = serde_json::json!({
508        "recipe": {
509            "flour": 4,
510            "sugar": 3,
511            "butter": 3,
512            "baking powder": 1,
513            "raisins": 50
514        },
515    });
516    let b64 = general_purpose::STANDARD.encode(serde_json::to_vec(&data).unwrap());
517    let res = client
518        .get(url)
519        .header("Cookie", format!("recipe={b64}"))
520        .send()
521        .await
522        .map_err(|_| test)?;
523    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
524    if json != data {
525        return Err(test);
526    }
527    test = (1, 2);
528    let data = serde_json::json!({
529        "recipe": {
530            "peanuts": 26,
531            "dough": 37,
532            "extra salt": 1,
533            "raisins": 50
534        },
535    });
536    let b64 = general_purpose::STANDARD.encode(serde_json::to_vec(&data).unwrap());
537    let res = client
538        .get(url)
539        .header("Cookie", format!("recipe={b64}"))
540        .send()
541        .await
542        .map_err(|_| test)?;
543    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
544    if json != data {
545        return Err(test);
546    }
547    // TASK 1 DONE
548    tx.send((true, 0).into()).await.unwrap();
549    tx.send(SubmissionUpdate::Save).await.unwrap();
550
551    // TASK 2
552    let url = &format!("{}/7/bake", base_url);
553    let test_bake = |test: (i32, i32), i: serde_json::Value, o: serde_json::Value| async move {
554        let client = new_client();
555        let b64 = general_purpose::STANDARD.encode(serde_json::to_vec(&i).unwrap());
556        let res = client
557            .get(url)
558            .header("Cookie", format!("recipe={b64}"))
559            .send()
560            .await
561            .map_err(|_| test)?;
562        let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
563        if json != o {
564            return Err(test);
565        }
566        Ok(())
567    };
568    test = (2, 1);
569    test_bake(
570        test,
571        serde_json::json!({
572            "recipe": {
573                "flour": 35,
574                "sugar": 56,
575                "butter": 3,
576                "baking powder": 1001,
577                "chocolate chips": 55
578            },
579            "pantry": {
580                "flour": 4045,
581                "sugar": 9606,
582                "butter": 99, // will land at 0
583                "baking powder": 8655432,
584                "chocolate chips": 4587
585            }
586        }),
587        serde_json::json!({
588            "cookies": 33,
589            "pantry": {
590                "flour": 2890,
591                "sugar": 7758,
592                "butter": 0,
593                "baking powder": 8622399,
594                "chocolate chips": 2772
595            }
596        }),
597    )
598    .await?;
599    test = (2, 2);
600    test_bake(
601        test,
602        serde_json::json!({
603            "recipe": {
604                "flour": 35,
605                "sugar": 56,
606                "butter": 3,
607                "baking powder": 1001,
608                "chocolate chips": 55
609            },
610            "pantry": {
611                "flour": 4045,
612                "sugar": 7606,
613                "butter": 100,
614                "baking powder": 865543211516164409i64,
615                "chocolate chips": 4587
616            }
617        }),
618        serde_json::json!({
619            "cookies": 33,
620            "pantry": {
621                "flour": 2890,
622                "sugar": 5758,
623                "butter": 1,
624                "baking powder": 865543211516131376i64,
625                "chocolate chips": 2772
626            }
627        }),
628    )
629    .await?;
630    // TASK 2 DONE
631    tx.send((false, 120).into()).await.unwrap();
632    tx.send(SubmissionUpdate::Save).await.unwrap();
633
634    // TASK 3
635    test = (3, 1);
636    test_bake(
637        test,
638        serde_json::json!({
639            "recipe": {
640                "chicken": 1,
641            },
642            "pantry": {
643                "chicken": 0,
644            }
645        }),
646        serde_json::json!({
647            "cookies": 0,
648            "pantry": {
649                "chicken": 0,
650            }
651        }),
652    )
653    .await?;
654    test = (3, 2);
655    test_bake(
656        test,
657        serde_json::json!({
658            "recipe": {
659                "cocoa bean": 1,
660                "chicken": 0,
661            },
662            "pantry": {
663                "cocoa bean": 5,
664                "corn": 5,
665                "cucumber": 0,
666            }
667        }),
668        serde_json::json!({
669            "cookies": 5,
670            "pantry": {
671                "cocoa bean": 0,
672                "corn": 5,
673                "cucumber": 0,
674            }
675        }),
676    )
677    .await?;
678    test = (3, 3);
679    test_bake(
680        test,
681        serde_json::json!({
682            "recipe": {
683                "cocoa bean": 1,
684                "chicken": 0,
685            },
686            "pantry": {
687                "cocoa bean": 5,
688                "chicken": 0,
689            }
690        }),
691        serde_json::json!({
692            "cookies": 5,
693            "pantry": {
694                "cocoa bean": 0,
695                "chicken": 0,
696            }
697        }),
698    )
699    .await?;
700    test = (3, 4);
701    test_bake(
702        test,
703        serde_json::json!({
704            "recipe": {
705                "cocoa bean": 1,
706                "chicken": 0,
707            },
708            "pantry": {
709                "cocoa bean": 5,
710            }
711        }),
712        serde_json::json!({
713            "cookies": 5,
714            "pantry": {
715                "cocoa bean": 0,
716            }
717        }),
718    )
719    .await?;
720    // TASK 3 DONE
721    tx.send((false, 100).into()).await.unwrap();
722
723    Ok(())
724}
725
726async fn validate_8(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
727    let client = new_client();
728    let mut test: TaskTest;
729    let tol = 0.001f64;
730    // TASK 1
731    test = (1, 1);
732    let url = &format!("{}/8/weight/225", base_url);
733    let res = client.get(url).send().await.map_err(|_| test)?;
734    let text = res.text().await.map_err(|_| test)?;
735    let num: f64 = text.parse().map_err(|_| test)?;
736    if !(num.is_finite() && (num - 16f64).abs() < tol) {
737        return Err(test);
738    }
739    test = (1, 2);
740    let url = &format!("{}/8/weight/393", base_url);
741    let res = client.get(url).send().await.map_err(|_| test)?;
742    let text = res.text().await.map_err(|_| test)?;
743    let num: f64 = text.parse().map_err(|_| test)?;
744    if !(num.is_finite() && (num - 5.2f64).abs() < tol) {
745        return Err(test);
746    }
747    test = (1, 3);
748    let url = &format!("{}/8/weight/92", base_url);
749    let res = client.get(url).send().await.map_err(|_| test)?;
750    let text = res.text().await.map_err(|_| test)?;
751    let num: f64 = text.parse().map_err(|_| test)?;
752    if !(num.is_finite() && (num - 0.1f64).abs() < tol) {
753        return Err(test);
754    }
755    // TASK 1 DONE
756    tx.send((true, 0).into()).await.unwrap();
757    tx.send(SubmissionUpdate::Save).await.unwrap();
758
759    // TASK 2
760    test = (2, 1);
761    let url = &format!("{}/8/drop/383", base_url);
762    let res = client.get(url).send().await.map_err(|_| test)?;
763    let text = res.text().await.map_err(|_| test)?;
764    let num: f64 = text.parse().map_err(|_| test)?;
765    if !(num.is_finite() && (num - 13316.953480432378f64).abs() < tol) {
766        return Err(test);
767    }
768    test = (2, 2);
769    let url = &format!("{}/8/drop/16", base_url);
770    let res = client.get(url).send().await.map_err(|_| test)?;
771    let text = res.text().await.map_err(|_| test)?;
772    let num: f64 = text.parse().map_err(|_| test)?;
773    if !(num.is_finite() && (num - 25.23212238397714f64).abs() < tol) {
774        return Err(test);
775    }
776    test = (2, 3);
777    let url = &format!("{}/8/drop/143", base_url);
778    let res = client.get(url).send().await.map_err(|_| test)?;
779    let text = res.text().await.map_err(|_| test)?;
780    let num: f64 = text.parse().map_err(|_| test)?;
781    if !(num.is_finite() && (num - 6448.2090536830465f64).abs() < tol) {
782        return Err(test);
783    }
784    // TASK 2 DONE
785    tx.send((false, 160).into()).await.unwrap();
786
787    Ok(())
788}
789
790async fn validate_11(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
791    let client = new_client();
792    let mut test: TaskTest;
793    // TASK 1
794    test = (1, 1);
795    let url = &format!("{}/11/assets/decoration.png", base_url);
796    let res = client.get(url).send().await.map_err(|_| test)?;
797    let headers = res.headers();
798    if !headers
799        .get("content-type")
800        .is_some_and(|v| v == "image/png")
801    {
802        return Err(test);
803    }
804    if !headers.get("content-length").is_some_and(|v| v == "787297") {
805        return Err(test);
806    }
807    let bytes = res.bytes().await.map_err(|_| test)?;
808    const EXPECTED: &[u8] = include_bytes!("../assets/decoration.png");
809    if bytes.to_vec().as_slice() != EXPECTED {
810        return Err(test);
811    }
812    // TASK 1 DONE
813    tx.send((true, 0).into()).await.unwrap();
814    tx.send(SubmissionUpdate::Save).await.unwrap();
815
816    // TASK 2
817    test = (2, 1);
818    let url = &format!("{}/11/red_pixels", base_url);
819    let form = Form::new().part(
820        "image",
821        Part::bytes(include_bytes!("../assets/decoration2.png").as_slice())
822            .file_name("decoration2.png")
823            .mime_str("image/png")
824            .unwrap(),
825    );
826    let res = client
827        .post(url)
828        .multipart(form)
829        .send()
830        .await
831        .map_err(|_| test)?;
832    let text = res.text().await.map_err(|_| test)?;
833    if text != "152107" {
834        return Err(test);
835    }
836    test = (2, 2);
837    let form = Form::new().part(
838        "image",
839        Part::bytes(include_bytes!("../assets/decoration3.png").as_slice())
840            .file_name("decoration3.png")
841            .mime_str("image/png")
842            .unwrap(),
843    );
844    let res = client
845        .post(url)
846        .multipart(form)
847        .send()
848        .await
849        .map_err(|_| test)?;
850    let text = res.text().await.map_err(|_| test)?;
851    if text != "40263" {
852        return Err(test);
853    }
854    test = (2, 3);
855    let form = Form::new().part(
856        "image",
857        Part::bytes(include_bytes!("../assets/decoration4.png").as_slice())
858            .file_name("decoration4.png")
859            .mime_str("image/png")
860            .unwrap(),
861    );
862    let res = client
863        .post(url)
864        .multipart(form)
865        .send()
866        .await
867        .map_err(|_| test)?;
868    let text = res.text().await.map_err(|_| test)?;
869    if text != "86869" {
870        return Err(test);
871    }
872    // TASK 2 DONE
873    tx.send((false, 200).into()).await.unwrap();
874
875    Ok(())
876}
877
878async fn validate_12(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
879    let client = new_client();
880    let mut test: TaskTest;
881    // TASK 1
882    test = (1, 1);
883    let url = &format!("{}/12/save/cch23", base_url);
884    let res = client.post(url).send().await.map_err(|_| test)?;
885    if res.status() != StatusCode::OK {
886        return Err(test);
887    }
888    sleep(Duration::from_secs(2)).await;
889    let url = &format!("{}/12/load/cch23", base_url);
890    let res = client.get(url).send().await.map_err(|_| test)?;
891    let text = res.text().await.map_err(|_| test)?;
892    if text != "2" {
893        return Err(test);
894    }
895    sleep(Duration::from_secs(2)).await;
896    let url = &format!("{}/12/load/cch23", base_url);
897    let res = client.get(url).send().await.map_err(|_| test)?;
898    let text = res.text().await.map_err(|_| test)?;
899    if text != "4" {
900        return Err(test);
901    }
902    test = (1, 2);
903    let url = &format!("{}/12/save/alpha", base_url);
904    let res = client.post(url).send().await.map_err(|_| test)?;
905    if res.status() != StatusCode::OK {
906        return Err(test);
907    }
908    sleep(Duration::from_secs(2)).await;
909    let url = &format!("{}/12/save/omega", base_url);
910    let res = client.post(url).send().await.map_err(|_| test)?;
911    if res.status() != StatusCode::OK {
912        return Err(test);
913    }
914    sleep(Duration::from_secs(2)).await;
915    let url = &format!("{}/12/load/alpha", base_url);
916    let res = client.get(url).send().await.map_err(|_| test)?;
917    let text = res.text().await.map_err(|_| test)?;
918    if text != "4" {
919        return Err(test);
920    }
921    let url = &format!("{}/12/save/alpha", base_url);
922    let res = client.post(url).send().await.map_err(|_| test)?;
923    if res.status() != StatusCode::OK {
924        return Err(test);
925    }
926    sleep(Duration::from_secs(1)).await;
927    let url = &format!("{}/12/load/omega", base_url);
928    let res = client.get(url).send().await.map_err(|_| test)?;
929    let text = res.text().await.map_err(|_| test)?;
930    if text != "3" {
931        return Err(test);
932    }
933    let url = &format!("{}/12/load/alpha", base_url);
934    let res = client.get(url).send().await.map_err(|_| test)?;
935    let text = res.text().await.map_err(|_| test)?;
936    if text != "1" {
937        return Err(test);
938    }
939    // TASK 1 DONE
940    tx.send((true, 0).into()).await.unwrap();
941    tx.send(SubmissionUpdate::Save).await.unwrap();
942
943    // TASK 2
944    test = (2, 1);
945    let url = &format!("{}/12/ulids", base_url);
946    let res = client
947        .post(url)
948        .json(&serde_json::json!([
949            "01BJQ0E1C3Z56ABCD0E11HYX4M",
950            "01BJQ0E1C3Z56ABCD0E11HYX5N",
951            "01BJQ0E1C3Z56ABCD0E11HYX6Q",
952            "01BJQ0E1C3Z56ABCD0E11HYX7R",
953            "01BJQ0E1C3Z56ABCD0E11HYX8P"
954        ]))
955        .send()
956        .await
957        .map_err(|_| test)?;
958    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
959    if json
960        != serde_json::json!([
961            "015cae07-0583-f94c-a5b1-a070431f7516",
962            "015cae07-0583-f94c-a5b1-a070431f74f8",
963            "015cae07-0583-f94c-a5b1-a070431f74d7",
964            "015cae07-0583-f94c-a5b1-a070431f74b5",
965            "015cae07-0583-f94c-a5b1-a070431f7494"
966        ])
967    {
968        return Err(test);
969    }
970    test = (2, 2);
971    let res = client
972        .post(url)
973        .json(&serde_json::json!([]))
974        .send()
975        .await
976        .map_err(|_| test)?;
977    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
978    if json != serde_json::json!([]) {
979        return Err(test);
980    }
981    // TASK 2 DONE
982    tx.send((false, 100).into()).await.unwrap();
983    tx.send(SubmissionUpdate::Save).await.unwrap();
984
985    // TASK 3
986    test = (3, 1);
987    let ids = serde_json::json!([
988        "00WEGGF0G0J5HEYXS3D7RWZGV8",
989        "76EP4G39R8JD1N8AQNYDVJBRCF",
990        "018CJ7KMG0051CDCS3B7BFJ3AK",
991        "00Y986KPG0AMGB78RD45E9109K",
992        "010451HTG0NYWMPWCEXG6AJ8F2",
993        "01HH9SJEG0KY16H81S3N1BMXM4",
994        "01HH9SJEG0P9M22Z9VGHH9C8CX",
995        "017F8YY0G0NQA16HHC2QT5JD6X",
996        "03QCPC7P003V1NND3B3QJW72QJ"
997    ]);
998    let url = &format!("{}/12/ulids/5", base_url);
999    let res = client.post(url).json(&ids).send().await.map_err(|_| test)?;
1000    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1001    if json
1002        != serde_json::json!({
1003            "christmas eve": 3,
1004            "weekday": 1,
1005            "in the future": 2,
1006            "LSB is 1": 5
1007        })
1008    {
1009        return Err(test);
1010    }
1011    test = (3, 2);
1012    let url = &format!("{}/12/ulids/0", base_url);
1013    let res = client.post(url).json(&ids).send().await.map_err(|_| test)?;
1014    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1015    if json
1016        != serde_json::json!({
1017            "christmas eve": 3,
1018            "weekday": 0,
1019            "in the future": 2,
1020            "LSB is 1": 5
1021        })
1022    {
1023        return Err(test);
1024    }
1025    test = (3, 3);
1026    let url = &format!("{}/12/ulids/2", base_url);
1027    let res = client
1028        .post(url)
1029        .json(&serde_json::json!(["04BJK8N300BAMR9SQQWPWHVYKZ"]))
1030        .send()
1031        .await
1032        .map_err(|_| test)?;
1033    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1034    if json
1035        != serde_json::json!({
1036            "christmas eve": 1,
1037            "weekday": 1,
1038            "in the future": 1,
1039            "LSB is 1": 1
1040        })
1041    {
1042        return Err(test);
1043    }
1044    // TASK 3 DONE
1045    tx.send((false, 200).into()).await.unwrap();
1046
1047    Ok(())
1048}
1049
1050async fn validate_13(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
1051    let client = new_client();
1052    let mut test: TaskTest;
1053    // TASK 1
1054    test = (1, 1);
1055    let url = &format!("{}/13/sql", base_url);
1056    let res = client.get(url).send().await.map_err(|_| test)?;
1057    let text = res.text().await.map_err(|_| test)?;
1058    if text != "20231213" {
1059        return Err(test);
1060    }
1061    // TASK 1 DONE
1062    tx.send((false, 0).into()).await.unwrap();
1063    tx.send(SubmissionUpdate::Save).await.unwrap();
1064
1065    // TASK 2
1066    test = (2, 1);
1067    let reset_url = &format!("{}/13/reset", base_url);
1068    let order_url = &format!("{}/13/orders", base_url);
1069    let total_url = &format!("{}/13/orders/total", base_url);
1070    let res = client.post(reset_url).send().await.map_err(|_| test)?;
1071    if res.status() != StatusCode::OK {
1072        return Err(test);
1073    }
1074    let res = client
1075        .post(order_url)
1076        .json(&serde_json::json!([
1077            {"id":1,"region_id":2,"gift_name":"Toy Train","quantity":5},
1078            {"id":2,"region_id":2,"gift_name":"Doll","quantity":8},
1079            {"id":3,"region_id":3,"gift_name":"Action Figure","quantity":12},
1080            {"id":4,"region_id":4,"gift_name":"Board Game","quantity":10},
1081            {"id":5,"region_id":2,"gift_name":"Teddy Bear","quantity":6},
1082            {"id":6,"region_id":3,"gift_name":"Toy Train","quantity":3},
1083        ]))
1084        .send()
1085        .await
1086        .map_err(|_| test)?;
1087    if res.status() != StatusCode::OK {
1088        return Err(test);
1089    }
1090    let res = client.get(total_url).send().await.map_err(|_| test)?;
1091    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1092    if json != serde_json::json!({"total": 44}) {
1093        return Err(test);
1094    }
1095    test = (2, 2);
1096    let res = client
1097        .post(order_url)
1098        .json(&serde_json::json!([
1099            {"id":123,"region_id":6,"gift_name":"Unknown","quantity":333},
1100        ]))
1101        .send()
1102        .await
1103        .map_err(|_| test)?;
1104    if res.status() != StatusCode::OK {
1105        return Err(test);
1106    }
1107    let res = client.get(total_url).send().await.map_err(|_| test)?;
1108    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1109    if json != serde_json::json!({"total": 377}) {
1110        return Err(test);
1111    }
1112    // TASK 2 DONE
1113    tx.send((true, 0).into()).await.unwrap();
1114    tx.send(SubmissionUpdate::Save).await.unwrap();
1115
1116    // TASK 3
1117    test = (3, 1);
1118    let popular_url = &format!("{}/13/orders/popular", base_url);
1119    let res = client.post(reset_url).send().await.map_err(|_| test)?;
1120    if res.status() != StatusCode::OK {
1121        return Err(test);
1122    }
1123    let res = client.get(popular_url).send().await.map_err(|_| test)?;
1124    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1125    if json != serde_json::json!({"popular": null}) {
1126        return Err(test);
1127    }
1128    test = (3, 2);
1129    let res = client
1130        .post(order_url)
1131        .json(&serde_json::json!([
1132            {"id":1,"region_id":2,"gift_name":"Lego Rocket","quantity":12},
1133            {"id":2,"region_id":2,"gift_name":"Action Figure","quantity":18},
1134            {"id":3,"region_id":5,"gift_name":"Toy Train","quantity":19},
1135            {"id":4,"region_id":5,"gift_name":"Lego Rocket","quantity":12},
1136            {"id":5,"region_id":4,"gift_name":"Toy Train","quantity":15},
1137            {"id":6,"region_id":2,"gift_name":"Toy Train","quantity":7},
1138            {"id":7,"region_id":3,"gift_name":"Toy Train","quantity":19},
1139            {"id":8,"region_id":4,"gift_name":"Action Figure","quantity":8},
1140            {"id":9,"region_id":2,"gift_name":"Toy Axe","quantity":15},
1141            {"id":10,"region_id":4,"gift_name":"Toy Axe","quantity":1},
1142            {"id":11,"region_id":2,"gift_name":"Toy Train","quantity":17},
1143            {"id":12,"region_id":4,"gift_name":"Toy Train","quantity":5},
1144            {"id":13,"region_id":4,"gift_name":"Sweater","quantity":20},
1145            {"id":14,"region_id":4,"gift_name":"Action Figure","quantity":7},
1146            {"id":15,"region_id":2,"gift_name":"Toy Train","quantity":16},
1147            {"id":16,"region_id":3,"gift_name":"Action Figure","quantity":12},
1148            {"id":17,"region_id":4,"gift_name":"Toy Axe","quantity":2},
1149            {"id":18,"region_id":3,"gift_name":"Toy Train","quantity":9},
1150            {"id":19,"region_id":2,"gift_name":"Sweater","quantity":9},
1151            {"id":20,"region_id":5,"gift_name":"Toy Train","quantity":9},
1152            {"id":21,"region_id":4,"gift_name":"Action Figure","quantity":11},
1153            {"id":22,"region_id":3,"gift_name":"Toy Train","quantity":7},
1154            {"id":23,"region_id":2,"gift_name":"Action Figure","quantity":5},
1155            {"id":24,"region_id":4,"gift_name":"Action Figure","quantity":17},
1156            {"id":25,"region_id":5,"gift_name":"Lego Rocket","quantity":6},
1157            {"id":26,"region_id":2,"gift_name":"Sweater","quantity":5},
1158            {"id":27,"region_id":5,"gift_name":"Toy Train","quantity":4},
1159            {"id":28,"region_id":4,"gift_name":"Lego Rocket","quantity":8},
1160            {"id":29,"region_id":2,"gift_name":"Toy Train","quantity":3},
1161            {"id":30,"region_id":4,"gift_name":"Toy Axe","quantity":20},
1162            {"id":31,"region_id":2,"gift_name":"Action Figure","quantity":5},
1163            {"id":32,"region_id":2,"gift_name":"Lego Rocket","quantity":10},
1164            {"id":33,"region_id":5,"gift_name":"Toy Train","quantity":4},
1165            {"id":34,"region_id":2,"gift_name":"Toy Axe","quantity":14},
1166            {"id":35,"region_id":3,"gift_name":"Action Figure","quantity":18},
1167            {"id":36,"region_id":5,"gift_name":"Toy Axe","quantity":10},
1168            {"id":37,"region_id":4,"gift_name":"Lego Rocket","quantity":6},
1169            {"id":38,"region_id":4,"gift_name":"Action Figure","quantity":16},
1170            {"id":39,"region_id":4,"gift_name":"Toy Axe","quantity":15},
1171            {"id":40,"region_id":5,"gift_name":"Lego Rocket","quantity":15},
1172            {"id":41,"region_id":5,"gift_name":"Action Figure","quantity":7},
1173            {"id":42,"region_id":3,"gift_name":"Action Figure","quantity":16},
1174            {"id":43,"region_id":3,"gift_name":"Toy Train","quantity":8},
1175            {"id":44,"region_id":4,"gift_name":"Action Figure","quantity":13},
1176            {"id":45,"region_id":3,"gift_name":"Lego Rocket","quantity":12},
1177            {"id":46,"region_id":3,"gift_name":"Toy Train","quantity":1},
1178            {"id":47,"region_id":2,"gift_name":"Toy Train","quantity":11},
1179            {"id":48,"region_id":5,"gift_name":"Action Figure","quantity":1},
1180            {"id":49,"region_id":4,"gift_name":"Toy Train","quantity":13},
1181            {"id":50,"region_id":5,"gift_name":"Action Figure","quantity":16},
1182            {"id":51,"region_id":4,"gift_name":"Toy Axe","quantity":19},
1183            {"id":52,"region_id":2,"gift_name":"Toy Train","quantity":14},
1184            {"id":53,"region_id":3,"gift_name":"Action Figure","quantity":16},
1185        ]))
1186        .send()
1187        .await
1188        .map_err(|_| test)?;
1189    if res.status() != StatusCode::OK {
1190        return Err(test);
1191    }
1192    let res = client.get(popular_url).send().await.map_err(|_| test)?;
1193    let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1194    if json != serde_json::json!({"popular": "Action Figure"}) {
1195        return Err(test);
1196    }
1197    // TASK 3 DONE
1198    tx.send((false, 100).into()).await.unwrap();
1199
1200    Ok(())
1201}
1202
1203async fn validate_14(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
1204    let client = new_client();
1205    let mut test: TaskTest;
1206    // TASK 1
1207    test = (1, 1);
1208    let url = &format!("{}/14/unsafe", base_url);
1209    let res = client
1210        .post(url)
1211        .json(&serde_json::json!({"content": "Bing Chilling 🥶🍦"}))
1212        .send()
1213        .await
1214        .map_err(|_| test)?;
1215    let text = res.text().await.map_err(|_| test)?;
1216    if text
1217        != "\
1218<html>
1219  <head>
1220    <title>CCH23 Day 14</title>
1221  </head>
1222  <body>
1223    Bing Chilling 🥶🍦
1224  </body>
1225</html>"
1226    {
1227        return Err(test);
1228    }
1229    test = (1, 2);
1230    let res = client
1231        .post(url)
1232        .json(&serde_json::json!({"content": r#"<script>alert("XSS Attack Success!")</script>"#}))
1233        .send()
1234        .await
1235        .map_err(|_| test)?;
1236    let text = res.text().await.map_err(|_| test)?;
1237    if text
1238        != "\
1239<html>
1240  <head>
1241    <title>CCH23 Day 14</title>
1242  </head>
1243  <body>
1244    <script>alert(\"XSS Attack Success!\")</script>
1245  </body>
1246</html>"
1247    {
1248        return Err(test);
1249    }
1250    // TASK 1 DONE
1251    tx.send((true, 0).into()).await.unwrap();
1252    tx.send(SubmissionUpdate::Save).await.unwrap();
1253
1254    // TASK 2
1255    test = (2, 1);
1256    let url = &format!("{}/14/safe", base_url);
1257    let res = client
1258        .post(url)
1259        .json(&serde_json::json!({"content": r#"<script>alert("XSS Attack Failed!")</script>"#}))
1260        .send()
1261        .await
1262        .map_err(|_| test)?;
1263    let text = res.text().await.map_err(|_| test)?;
1264    if text
1265        != "\
1266<html>
1267  <head>
1268    <title>CCH23 Day 14</title>
1269  </head>
1270  <body>
1271    &lt;script&gt;alert(&quot;XSS Attack Failed!&quot;)&lt;/script&gt;
1272  </body>
1273</html>"
1274    {
1275        return Err(test);
1276    }
1277    // TASK 2 DONE
1278    tx.send((false, 100).into()).await.unwrap();
1279
1280    Ok(())
1281}
1282
1283struct JSONTester {
1284    client: reqwest::Client,
1285    url: String,
1286}
1287
1288impl JSONTester {
1289    fn new(url: String) -> Self {
1290        Self {
1291            client: new_client(),
1292            url,
1293        }
1294    }
1295    async fn test(
1296        &self,
1297        test: TaskTest,
1298        i: &serde_json::Value,
1299        code: StatusCode,
1300        o: &serde_json::Value,
1301    ) -> ValidateResult {
1302        let res = self
1303            .client
1304            .post(&self.url)
1305            .json(i)
1306            .send()
1307            .await
1308            .map_err(|_| test)?;
1309        if res.status() != code {
1310            return Err(test);
1311        }
1312        let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1313        if json != *o {
1314            return Err(test);
1315        }
1316        Ok(())
1317    }
1318}
1319
1320async fn validate_15(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
1321    // TASK 1
1322    let t = JSONTester::new(format!("{}/15/nice", base_url));
1323    t.test(
1324        (1, 1),
1325        &serde_json::json!({"input": "hello there"}),
1326        StatusCode::OK,
1327        &serde_json::json!({"result": "nice"}),
1328    )
1329    .await?;
1330    t.test(
1331        (1, 2),
1332        &serde_json::json!({"input": "he77o there"}),
1333        StatusCode::BAD_REQUEST,
1334        &serde_json::json!({"result": "naughty"}),
1335    )
1336    .await?;
1337    t.test(
1338        (1, 3),
1339        &serde_json::json!({"input": "hello"}),
1340        StatusCode::BAD_REQUEST,
1341        &serde_json::json!({"result": "naughty"}),
1342    )
1343    .await?;
1344    t.test(
1345        (1, 4),
1346        &serde_json::json!({"input": "hello xylophone"}),
1347        StatusCode::BAD_REQUEST,
1348        &serde_json::json!({"result": "naughty"}),
1349    )
1350    .await?;
1351    t.test(
1352        (1, 5),
1353        &serde_json::json!({"input": "password"}),
1354        StatusCode::BAD_REQUEST,
1355        &serde_json::json!({"result": "naughty"}),
1356    )
1357    .await?;
1358    let test = (1, 6);
1359    let res = new_client()
1360        .post(format!("{}/15/nice", base_url))
1361        .header(CONTENT_TYPE, HeaderValue::from_static("application/json"))
1362        .body("WooooOOOooOOOoooOO 👻")
1363        .send()
1364        .await
1365        .map_err(|_| test)?;
1366    if res.status() != StatusCode::BAD_REQUEST {
1367        return Err(test);
1368    }
1369    // TASK 1 DONE
1370    tx.send((true, 0).into()).await.unwrap();
1371    tx.send(SubmissionUpdate::Save).await.unwrap();
1372
1373    // TASK 2
1374    let t = JSONTester::new(format!("{}/15/game", base_url));
1375    t.test(
1376        (2, 1),
1377        &serde_json::json!({"input": "mario"}),
1378        StatusCode::BAD_REQUEST,
1379        &serde_json::json!({"result": "naughty", "reason": "8 chars"}),
1380    )
1381    .await?;
1382    t.test(
1383        (2, 2),
1384        &serde_json::json!({"input": "mariobro"}),
1385        StatusCode::BAD_REQUEST,
1386        &serde_json::json!({"result": "naughty", "reason": "more types of chars"}),
1387    )
1388    .await?;
1389    t.test(
1390        (2, 3),
1391        &serde_json::json!({"input": "EEEEEEEEEEE"}),
1392        StatusCode::BAD_REQUEST,
1393        &serde_json::json!({"result": "naughty", "reason": "more types of chars"}),
1394    )
1395    .await?;
1396    t.test(
1397        (2, 4),
1398        &serde_json::json!({"input": "E3E3E3E3E3E"}),
1399        StatusCode::BAD_REQUEST,
1400        &serde_json::json!({"result": "naughty", "reason": "more types of chars"}),
1401    )
1402    .await?;
1403    t.test(
1404        (2, 5),
1405        &serde_json::json!({"input": "e3E3e#eE#ee3#EeE3"}),
1406        StatusCode::BAD_REQUEST,
1407        &serde_json::json!({"result": "naughty", "reason": "55555"}),
1408    )
1409    .await?;
1410    t.test(
1411        (2, 6),
1412        &serde_json::json!({"input": "Password12345"}),
1413        StatusCode::BAD_REQUEST,
1414        &serde_json::json!({"result": "naughty", "reason": "math is hard"}),
1415    )
1416    .await?;
1417    t.test(
1418        (2, 7),
1419        &serde_json::json!({"input": "2 00 2 3 OOgaBooga"}),
1420        StatusCode::BAD_REQUEST,
1421        &serde_json::json!({"result": "naughty", "reason": "math is hard"}),
1422    )
1423    .await?;
1424    t.test(
1425        (2, 8),
1426        &serde_json::json!({"input": "2+2/2-8*8 = 1-2000 OOgaBooga"}),
1427        StatusCode::NOT_ACCEPTABLE,
1428        &serde_json::json!({"result": "naughty", "reason": "not joyful enough"}),
1429    )
1430    .await?;
1431    t.test(
1432        (2, 9),
1433        &serde_json::json!({"input": "2000.23.A yoyoj"}),
1434        StatusCode::NOT_ACCEPTABLE,
1435        &serde_json::json!({"result": "naughty", "reason": "not joyful enough"}),
1436    )
1437    .await?;
1438    t.test(
1439        (2, 10),
1440        &serde_json::json!({"input": "2000.23.A joy joy"}),
1441        StatusCode::NOT_ACCEPTABLE,
1442        &serde_json::json!({"result": "naughty", "reason": "not joyful enough"}),
1443    )
1444    .await?;
1445    t.test(
1446        (2, 11),
1447        &serde_json::json!({"input": "2000.23.A joyo"}),
1448        StatusCode::NOT_ACCEPTABLE,
1449        &serde_json::json!({"result": "naughty", "reason": "not joyful enough"}),
1450    )
1451    .await?;
1452    t.test(
1453        (2, 12),
1454        &serde_json::json!({"input": "2000.23.A j  ;)  o  ;)  y "}),
1455        StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS,
1456        &serde_json::json!({"result": "naughty", "reason": "illegal: no sandwich"}),
1457    )
1458    .await?;
1459    t.test(
1460        (2, 13),
1461        &serde_json::json!({"input": "2020.3.A j  ;)  o  ;)  y"}),
1462        StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS,
1463        &serde_json::json!({"result": "naughty", "reason": "illegal: no sandwich"}),
1464    )
1465    .await?;
1466    t.test(
1467        (2, 14),
1468        &serde_json::json!({"input": "2000.23.A j  ;)  o  ;)  y AzA"}),
1469        StatusCode::RANGE_NOT_SATISFIABLE,
1470        &serde_json::json!({"result": "naughty", "reason": "outranged"}),
1471    )
1472    .await?;
1473    t.test(
1474        (2, 15),
1475        &serde_json::json!({"input": "2000.23.A j  ;)  o  ;)  y⥿ AzA"}),
1476        StatusCode::RANGE_NOT_SATISFIABLE,
1477        &serde_json::json!({"result": "naughty", "reason": "outranged"}),
1478    )
1479    .await?;
1480    t.test(
1481        (2, 16),
1482        &serde_json::json!({"input": "2000.23.A j  ;)  o  ;)  y ⦄AzA"}),
1483        StatusCode::UPGRADE_REQUIRED,
1484        &serde_json::json!({"result": "naughty", "reason": "😳"}),
1485    )
1486    .await?;
1487    t.test(
1488        (2, 17),
1489        &serde_json::json!({"input": "2000.23.A j  🥶  o  🍦  y ⦄AzA"}),
1490        StatusCode::IM_A_TEAPOT,
1491        &serde_json::json!({"result": "naughty", "reason": "not a coffee brewer"}),
1492    )
1493    .await?;
1494    t.test(
1495        (2, 18),
1496        &serde_json::json!({"input": "2000.23.A j ⦖⦖⦖⦖⦖⦖⦖⦖ 🥶  o  🍦  y ⦄AzA"}),
1497        StatusCode::OK,
1498        &serde_json::json!({"result": "nice", "reason": "that's a nice password"}),
1499    )
1500    .await?;
1501    // TASK 2 DONE
1502    tx.send((false, 400).into()).await.unwrap();
1503
1504    Ok(())
1505}
1506
1507struct RegionGiftTester {
1508    client: reqwest::Client,
1509    reset_url: String,
1510    regions_url: String,
1511    orders_url: String,
1512    final_url: String,
1513}
1514
1515impl RegionGiftTester {
1516    async fn test(
1517        &self,
1518        test: TaskTest,
1519        i1: &serde_json::Value,
1520        i2: &serde_json::Value,
1521        o: &serde_json::Value,
1522    ) -> ValidateResult {
1523        let res = self
1524            .client
1525            .post(&self.reset_url)
1526            .send()
1527            .await
1528            .map_err(|_| test)?;
1529        if res.status() != StatusCode::OK {
1530            return Err(test);
1531        }
1532        let res = self
1533            .client
1534            .post(&self.regions_url)
1535            .json(i1)
1536            .send()
1537            .await
1538            .map_err(|_| test)?;
1539        if res.status() != StatusCode::OK {
1540            return Err(test);
1541        }
1542        let res = self
1543            .client
1544            .post(&self.orders_url)
1545            .json(i2)
1546            .send()
1547            .await
1548            .map_err(|_| test)?;
1549        if res.status() != StatusCode::OK {
1550            return Err(test);
1551        }
1552        let res = self
1553            .client
1554            .get(&self.final_url)
1555            .send()
1556            .await
1557            .map_err(|_| test)?;
1558        if res.status() != StatusCode::OK {
1559            return Err(test);
1560        }
1561        let json = res.json::<serde_json::Value>().await.map_err(|_| test)?;
1562        if json != *o {
1563            return Err(test);
1564        }
1565        Ok(())
1566    }
1567}
1568
1569async fn validate_18(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
1570    // TASK 1
1571    let t = RegionGiftTester {
1572        client: new_client(),
1573        reset_url: format!("{}/18/reset", base_url),
1574        regions_url: format!("{}/18/regions", base_url),
1575        orders_url: format!("{}/18/orders", base_url),
1576        final_url: format!("{}/18/regions/total", base_url),
1577    };
1578    t.test(
1579        (1, 1),
1580        &serde_json::json!([{"id":1,"name":"North Pole"}]),
1581        &serde_json::json!([]),
1582        &serde_json::json!([]),
1583    )
1584    .await?;
1585    t.test(
1586        (1, 2),
1587        &serde_json::json!([]),
1588        &serde_json::json!([{"id":1,"region_id":2,"gift_name":"Board Game","quantity":5}]),
1589        &serde_json::json!([]),
1590    )
1591    .await?;
1592    t.test(
1593        (1, 3),
1594        &serde_json::json!([{"id":1,"name":"A"}]),
1595        &serde_json::json!([{"id":1,"region_id":1,"gift_name":"A","quantity":1}]),
1596        &serde_json::json!([{"region":"A","total":1}]),
1597    )
1598    .await?;
1599    t.test(
1600        (1, 4),
1601        &serde_json::json!([{"id":1,"name":"A"}]),
1602        &serde_json::json!([
1603            {"id":1,"region_id":1,"gift_name":"A","quantity":1},
1604            {"id":2,"region_id":1,"gift_name":"A","quantity":1},
1605            {"id":3,"region_id":1,"gift_name":"A","quantity":1}
1606        ]),
1607        &serde_json::json!([{"region":"A","total":3}]),
1608    )
1609    .await?;
1610    t.test(
1611        (1, 5),
1612        &serde_json::json!([
1613            {"id":1,"name":"A"},
1614            {"id":2,"name":"B"}
1615        ]),
1616        &serde_json::json!([
1617            {"id":1,"region_id":1,"gift_name":"A","quantity":1},
1618            {"id":2,"region_id":1,"gift_name":"A","quantity":1},
1619            {"id":3,"region_id":2,"gift_name":"B","quantity":1}
1620        ]),
1621        &serde_json::json!([
1622            {"region":"A","total":2},
1623            {"region":"B","total":1}
1624        ]),
1625    )
1626    .await?;
1627    t.test(
1628        (1, 6),
1629        &serde_json::json!([
1630            {"id":1,"name":"A"},
1631            {"id":2,"name":"B"}
1632        ]),
1633        &serde_json::json!([
1634            {"id":1,"region_id":1,"gift_name":"A","quantity":1},
1635            {"id":2,"region_id":1,"gift_name":"A","quantity":1},
1636            {"id":3,"region_id":3,"gift_name":"C","quantity":1}
1637        ]),
1638        &serde_json::json!([{"region":"A","total":2}]),
1639    )
1640    .await?;
1641    t.test(
1642        (1, 7),
1643        &serde_json::json!([{"id":1,"name":"A"}]),
1644        &serde_json::json!([{"id":1,"region_id":1,"gift_name":"A","quantity":555555555}]),
1645        &serde_json::json!([{"region":"A","total":555555555}]),
1646    )
1647    .await?;
1648    t.test(
1649        (1, 8),
1650        &serde_json::json!([{"id":-1,"name":"A"}]),
1651        &serde_json::json!([
1652            {"id":-1,"region_id":-1,"gift_name":"A","quantity":-1},
1653            {"id":0,"region_id":-1,"gift_name":"A","quantity":1}
1654        ]),
1655        &serde_json::json!([{"region":"A","total":0}]),
1656    )
1657    .await?;
1658    // TASK 1 DONE
1659    tx.send((true, 0).into()).await.unwrap();
1660    tx.send(SubmissionUpdate::Save).await.unwrap();
1661
1662    // TASK 2
1663    let t = RegionGiftTester {
1664        client: new_client(),
1665        reset_url: format!("{}/18/reset", base_url),
1666        regions_url: format!("{}/18/regions", base_url),
1667        orders_url: format!("{}/18/orders", base_url),
1668        final_url: format!("{}/18/regions/top_list/2", base_url),
1669    };
1670    t.test(
1671        (2, 1),
1672        &serde_json::json!([]),
1673        &serde_json::json!([]),
1674        &serde_json::json!([]),
1675    )
1676    .await?;
1677    t.test(
1678        (2, 2),
1679        &serde_json::json!([{"id":1,"name":"A"}]),
1680        &serde_json::json!([]),
1681        &serde_json::json!([{"region":"A","top_gifts":[]}]),
1682    )
1683    .await?;
1684    t.test(
1685        (2, 3),
1686        &serde_json::json!([]),
1687        &serde_json::json!([{"id":1,"region_id":2,"gift_name":"B","quantity":5}]),
1688        &serde_json::json!([]),
1689    )
1690    .await?;
1691    t.test(
1692        (2, 4),
1693        &serde_json::json!([{"id":1,"name":"A"}]),
1694        &serde_json::json!([{"id":1,"region_id":2,"gift_name":"B","quantity":5}]),
1695        &serde_json::json!([{"region":"A","top_gifts":[]}]),
1696    )
1697    .await?;
1698    t.test(
1699        (2, 5),
1700        &serde_json::json!([{"id":1,"name":"A"}]),
1701        &serde_json::json!([
1702            {"id":1,"region_id":1,"gift_name":"B","quantity":10},
1703            {"id":2,"region_id":1,"gift_name":"A","quantity":5},
1704            {"id":3,"region_id":1,"gift_name":"A","quantity":5},
1705            {"id":4,"region_id":1,"gift_name":"C","quantity":9}
1706        ]),
1707        &serde_json::json!([{"region":"A","top_gifts":["A","B"]}]),
1708    )
1709    .await?;
1710    let regions = serde_json::json!([
1711        {"id":1,"name":"North Pole"},
1712        {"id":2,"name":"Europe"},
1713        {"id":3,"name":"North America"},
1714        {"id":4,"name":"South America"},
1715        {"id":5,"name":"Africa"},
1716        {"id":6,"name":"Asia"},
1717        {"id":7,"name":"Oceania"}
1718    ]);
1719    t.test(
1720        (2, 6),
1721        &regions,
1722        &serde_json::json!([
1723            {"id":1,"region_id":2,"gift_name":"Toy Train","quantity":5},
1724            {"id":2,"region_id":2,"gift_name":"Toy Train","quantity":3},
1725            {"id":3,"region_id":2,"gift_name":"Doll","quantity":8},
1726            {"id":4,"region_id":3,"gift_name":"Toy Train","quantity":3},
1727            {"id":5,"region_id":2,"gift_name":"Teddy Bear","quantity":6},
1728            {"id":6,"region_id":3,"gift_name":"Action Figure","quantity":12},
1729            {"id":7,"region_id":4,"gift_name":"Board Game","quantity":10},
1730            {"id":8,"region_id":3,"gift_name":"Teddy Bear","quantity":1},
1731            {"id":9,"region_id":3,"gift_name":"Teddy Bear","quantity":2}
1732        ]),
1733        &serde_json::json!([
1734            {"region":"Africa","top_gifts":[]},
1735            {"region":"Asia","top_gifts":[]},
1736            {"region":"Europe","top_gifts":["Doll","Toy Train"]},
1737            {"region":"North America","top_gifts":["Action Figure","Teddy Bear"]},
1738            {"region":"North Pole","top_gifts":[]},
1739            {"region":"Oceania","top_gifts":[]},
1740            {"region":"South America","top_gifts":["Board Game"]},
1741        ]),
1742    )
1743    .await?;
1744    let t = RegionGiftTester {
1745        client: new_client(),
1746        reset_url: format!("{}/18/reset", base_url),
1747        regions_url: format!("{}/18/regions", base_url),
1748        orders_url: format!("{}/18/orders", base_url),
1749        final_url: format!("{}/18/regions/top_list/3", base_url),
1750    };
1751    t.test(
1752        (2, 7),
1753        &regions,
1754        &serde_json::json!([
1755            {"id":1,"region_id":2,"gift_name":"Toy Train","quantity":5},
1756            {"id":2,"region_id":2,"gift_name":"Toy Train","quantity":3},
1757            {"id":3,"region_id":2,"gift_name":"Doll","quantity":8},
1758            {"id":4,"region_id":3,"gift_name":"Toy Train","quantity":3},
1759            {"id":5,"region_id":2,"gift_name":"Teddy Bear","quantity":6},
1760            {"id":6,"region_id":3,"gift_name":"Action Figure","quantity":12},
1761            {"id":7,"region_id":4,"gift_name":"Board Game","quantity":10},
1762            {"id":8,"region_id":3,"gift_name":"Teddy Bear","quantity":1},
1763            {"id":9,"region_id":3,"gift_name":"Teddy Bear","quantity":2}
1764        ]),
1765        &serde_json::json!([
1766            {"region":"Africa","top_gifts":[]},
1767            {"region":"Asia","top_gifts":[]},
1768            {"region":"Europe","top_gifts":["Doll","Toy Train","Teddy Bear"]},
1769            {"region":"North America","top_gifts":["Action Figure","Teddy Bear","Toy Train"]},
1770            {"region":"North Pole","top_gifts":[]},
1771            {"region":"Oceania","top_gifts":[]},
1772            {"region":"South America","top_gifts":["Board Game"]},
1773        ]),
1774    )
1775    .await?;
1776    let t = RegionGiftTester {
1777        client: new_client(),
1778        reset_url: format!("{}/18/reset", base_url),
1779        regions_url: format!("{}/18/regions", base_url),
1780        orders_url: format!("{}/18/orders", base_url),
1781        final_url: format!("{}/18/regions/top_list/0", base_url),
1782    };
1783    t.test(
1784        (2, 8),
1785        &serde_json::json!([{"id":1,"name":"A"}]),
1786        &serde_json::json!([{"id":1,"region_id":1,"gift_name":"A","quantity":555555555}]),
1787        &serde_json::json!([{"region":"A","top_gifts":[]}]),
1788    )
1789    .await?;
1790    // TASK 2 DONE
1791    tx.send((false, 600).into()).await.unwrap();
1792
1793    Ok(())
1794}
1795
1796struct WS {
1797    test: TaskTest,
1798    w: SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>,
1799    r: SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>,
1800}
1801
1802impl WS {
1803    async fn new(test: TaskTest, url: String) -> Result<Self, TaskTest> {
1804        let (s, _) = tokio_tungstenite::connect_async(url)
1805            .await
1806            .map_err(|_| test)?;
1807        let (w, r) = s.split();
1808
1809        Ok(Self { test, w, r })
1810    }
1811
1812    async fn send(&mut self, msg: impl Into<String>) -> ValidateResult {
1813        self.w
1814            .send(Message::Text(msg.into()))
1815            .await
1816            .map_err(|_| self.test)
1817    }
1818
1819    async fn send_tweet(&mut self, msg: impl Into<String>) -> ValidateResult {
1820        self.send(serde_json::to_string(&serde_json::json!({"message": msg.into()})).unwrap())
1821            .await
1822    }
1823
1824    async fn recv(&mut self) -> Result<String, TaskTest> {
1825        let Some(Ok(Message::Text(text))) = self.r.next().await else {
1826            return Err(self.test);
1827        };
1828
1829        Ok(text)
1830    }
1831
1832    async fn recv_str(&mut self, exp: &str) -> ValidateResult {
1833        let text = self.recv().await?;
1834        if text != exp {
1835            return Err(self.test);
1836        }
1837
1838        Ok(())
1839    }
1840
1841    async fn recv_json(&mut self, exp: &serde_json::Value) -> ValidateResult {
1842        let text = self.recv().await?;
1843        let json = serde_json::from_str::<serde_json::Value>(&text).map_err(|_| self.test)?;
1844        if &json != exp {
1845            return Err(self.test);
1846        }
1847
1848        Ok(())
1849    }
1850
1851    async fn close(mut self) -> ValidateResult {
1852        self.w.close().await.map_err(|_| self.test)?;
1853
1854        Ok(())
1855    }
1856}
1857
1858async fn validate_19(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
1859    let mut test: TaskTest;
1860    let ws_base_url = format!(
1861        "ws{}",
1862        base_url
1863            .strip_prefix("http")
1864            .expect("url to begin with http")
1865    );
1866    // TASK 1
1867    test = (1, 1);
1868    let mut ws = WS::new(test, format!("{}/19/ws/ping", ws_base_url)).await?;
1869    ws.send("ping").await?;
1870    tokio::select! {
1871        _ = ws.recv() => {
1872            return Err(test);
1873        },
1874        _ = sleep(Duration::from_secs(1)) => (),
1875    };
1876    ws.send("serve").await?;
1877    ws.send("ping").await?;
1878    ws.recv_str("pong").await?;
1879    test = (1, 2);
1880    ws.test = test;
1881    ws.send("ding").await?;
1882    tokio::select! {
1883        _ = ws.recv() => {
1884            return Err(test);
1885        },
1886        _ = sleep(Duration::from_secs(1)) => (),
1887    };
1888    test = (1, 3);
1889    ws.test = test;
1890    ws.send("ping").await?;
1891    ws.send("ping").await?;
1892    ws.recv_str("pong").await?;
1893    ws.recv_str("pong").await?;
1894    tokio::select! {
1895        _ = ws.recv() => {
1896            return Err(test);
1897        },
1898        _ = sleep(Duration::from_millis(500)) => (),
1899    };
1900    ws.close().await?;
1901    // TASK 1 DONE
1902    tx.send((true, 0).into()).await.unwrap();
1903    tx.send(SubmissionUpdate::Save).await.unwrap();
1904
1905    // TASK 2
1906    let reset_url = &format!("{}/19/reset", base_url);
1907    let reset = || async move {
1908        let client = new_client();
1909        let res = client.post(reset_url).send().await.map_err(|_| ())?;
1910        if res.status() != StatusCode::OK {
1911            return Err(());
1912        }
1913        Ok(())
1914    };
1915    let views_url = &format!("{}/19/views", base_url);
1916    let ensure_views = |v: u32| async move {
1917        let client = new_client();
1918        let res = client.get(views_url).send().await.map_err(|_| ())?;
1919        let text = res.text().await.map_err(|_| ())?;
1920        if text != v.to_string() {
1921            return Err(());
1922        }
1923        Ok(())
1924    };
1925
1926    test = (2, 1);
1927    reset().await.map_err(|_| test)?;
1928    ensure_views(0).await.map_err(|_| test)?;
1929
1930    test = (2, 2);
1931    let mut elon = WS::new(test, format!("{}/19/ws/room/1/user/elonmusk", ws_base_url)).await?;
1932    let s = "Next I'm buying Coca-Cola to put the cocaine back in";
1933    elon.send_tweet(s).await?;
1934    elon.recv_json(&serde_json::json!({"user": "elonmusk", "message": s}))
1935        .await?;
1936    ensure_views(1).await.map_err(|_| test)?;
1937
1938    test = (2, 3);
1939    let s = "I've concocted a whimsical idea to bring a bit of the ol' history back to life by attempting to put the cocaine back in Coca-Cola, rekindling the rebellious spirit of its original formulation";
1940    elon.send_tweet(s).await?;
1941    tokio::select! {
1942        _ = elon.recv() => {
1943            return Err(test);
1944        },
1945        _ = sleep(Duration::from_secs(1)) => (),
1946    };
1947    ensure_views(1).await.map_err(|_| test)?;
1948    elon.close().await?;
1949    sleep(Duration::from_millis(10)).await;
1950
1951    test = (2, 4);
1952    reset().await.map_err(|_| test)?;
1953    ensure_views(0).await.map_err(|_| test)?;
1954    let mut a1 = WS::new(test, format!("{}/19/ws/room/44/user/annifrid", ws_base_url)).await?;
1955    let mut b1 = WS::new(test, format!("{}/19/ws/room/55/user/bjorn", ws_base_url)).await?;
1956    let mut b2 = WS::new(test, format!("{}/19/ws/room/55/user/benny", ws_base_url)).await?;
1957    let mut a2 = WS::new(test, format!("{}/19/ws/room/44/user/agnetha", ws_base_url)).await?;
1958    let l1 = "thank you for the music";
1959    let l2 = "the songs i'm singing";
1960    let l3 = "thanks for all";
1961    let l4 = "the joy they're bringing";
1962    let l5 = "who can live without it";
1963    let l6 = "i ask in all honesty";
1964    let x1 = "uhhhhhhhh?";
1965    let x2 = "wazzaaaaa?";
1966    a1.send_tweet(l1).await?;
1967    sleep(Duration::from_millis(10)).await;
1968    a2.send_tweet(l2).await?;
1969    sleep(Duration::from_millis(10)).await;
1970    a1.send_tweet(l3).await?;
1971    sleep(Duration::from_millis(10)).await;
1972    b1.send_tweet(x1).await?;
1973    sleep(Duration::from_millis(10)).await;
1974    a2.send_tweet(l4).await?;
1975    sleep(Duration::from_millis(10)).await;
1976    a1.send_tweet(l5).await?;
1977    sleep(Duration::from_millis(10)).await;
1978    a1.recv_json(&serde_json::json!({"user": "annifrid", "message": l1}))
1979        .await?;
1980    a2.recv_json(&serde_json::json!({"user": "annifrid", "message": l1}))
1981        .await?;
1982    a1.recv_json(&serde_json::json!({"user": "agnetha", "message": l2}))
1983        .await?;
1984    a2.recv_json(&serde_json::json!({"user": "agnetha", "message": l2}))
1985        .await?;
1986    a1.recv_json(&serde_json::json!({"user": "annifrid", "message": l3}))
1987        .await?;
1988    a2.recv_json(&serde_json::json!({"user": "annifrid", "message": l3}))
1989        .await?;
1990    a1.recv_json(&serde_json::json!({"user": "agnetha", "message": l4}))
1991        .await?;
1992    a2.recv_json(&serde_json::json!({"user": "agnetha", "message": l4}))
1993        .await?;
1994    a1.recv_json(&serde_json::json!({"user": "annifrid", "message": l5}))
1995        .await?;
1996    a2.recv_json(&serde_json::json!({"user": "annifrid", "message": l5}))
1997        .await?;
1998    sleep(Duration::from_millis(10)).await;
1999    ensure_views(12).await.map_err(|_| test)?;
2000
2001    test = (2, 5);
2002    a1.close().await?;
2003    sleep(Duration::from_millis(10)).await;
2004    a2.send_tweet(l6).await?;
2005    a2.recv_json(&serde_json::json!({"user": "agnetha", "message": l6}))
2006        .await?;
2007    sleep(Duration::from_millis(10)).await;
2008    ensure_views(13).await.map_err(|_| test)?;
2009
2010    test = (2, 6);
2011    let mut a1 = WS::new(test, format!("{}/19/ws/room/55/user/annifrid", ws_base_url)).await?;
2012    tokio::select! {
2013        _ = a1.recv() => {
2014            return Err(test);
2015        },
2016        _ = sleep(Duration::from_secs(1)) => (),
2017    };
2018    b1.recv_json(&serde_json::json!({"user": "bjorn", "message": x1}))
2019        .await?;
2020    b2.recv_json(&serde_json::json!({"user": "bjorn", "message": x1}))
2021        .await?;
2022    a1.send_tweet(x2).await?;
2023    sleep(Duration::from_millis(10)).await;
2024    b1.close().await?;
2025    a1.send_tweet(x2).await?;
2026    b2.recv_json(&serde_json::json!({"user": "annifrid", "message": x2}))
2027        .await?;
2028    b2.recv_json(&serde_json::json!({"user": "annifrid", "message": x2}))
2029        .await?;
2030    a1.recv_json(&serde_json::json!({"user": "annifrid", "message": x2}))
2031        .await?;
2032    a1.recv_json(&serde_json::json!({"user": "annifrid", "message": x2}))
2033        .await?;
2034    sleep(Duration::from_millis(10)).await;
2035    ensure_views(18).await.map_err(|_| test)?;
2036
2037    test = (2, 7);
2038    reset().await.map_err(|_| test)?;
2039    ensure_views(0).await.map_err(|_| test)?;
2040    // generated with https://github.com/orhun/godsays
2041    let phrases = Arc::new([
2042        "Okilydokily Give me praise Shhh how high umm what now epic fail mine",
2043        "quite Wow Shhh driving wot exorbitant Church",
2044        "whatcha talkin' 'bout chaos look buddy husband good pow Shalom",
2045        "joking don't have a cow so let it be written you should be so lucky taxes wonderbread spirit",
2046        "radio dean scream slumin big fish begs the question unemployment red fang",
2047        "radio Is that your final answer how goes it where's the love unsung hero yep fool",
2048        "yeah ghetto pardon the french happy middle class what a mess Isn't that special",
2049        "incoming you better not husband hope driving Watch this thank you very much",
2050        "I didn't see that sex won't you be my neighbor What take your pick naughty delicious",
2051        "you're in big trouble hypocrite won't you be my neighbor not in kansas anymore angel joy look on the brightside",
2052        "money freak joyful bizarre ahh go ahead make my day HolySpirit",
2053        "Han shot first awesome CIA what's up king of mars what's the plan do you like it",
2054        "woot ridiculous in a perfect world in other words It's nice being God I was just thinking joker",
2055        "lying depressing gluttony thank you very much think you could do better charity rip off",
2056        "how come You da man gosh chaos what a mess frown vengeance",
2057        "when hell freezes over resume theft I had a crazy dream dude such a scoffer not good Wow",
2058        "in a perfect world rose colored glasses quite That's gonna leave a mark slumin That's my favorite I have an idea",
2059        "you don't say I'm not sure what a nightmare well I never be quiet bird fortitude when hell freezes over",
2060        "scum you're in big trouble you see the light I'm bored who are you to judge because I said so by the way",
2061        "nevada cheerful vermin threads boss Yes you are I planned that",
2062        "high mucky muck Isn't that special what a mess mine pet energy that's your opinion",
2063        "et tu who's to say tattle tale oh my I'm good you good you owe me yuck",
2064        "praying patience genius I'm in suspense how high Venus I didn't do it",
2065        "Terry the Mom rum bitty di do it Zap I veto that",
2066        "hotel I got your back on the otherhand not good chess chill out talk to my lawyer",
2067        "in a perfect world I'm on a roll Yawn rubbish boss hold on a minute sports",
2068        "Varoom it'd take a miracle ohh thank you naughty Terry make my day outrageous",
2069        "atrocious Icarus hate piety one small step phasors on stun take your pick",
2070        "whazza matter for you not a chance in hell ridiculous whoop there it is little fish hilarious close your eyes",
2071        "you'll see yep this might end badly news to me red fang that's for me to know you're nuts",
2072        "what part of God do you not understand what's it to you laziness I donno ha whale beam me up",
2073        "sess me yep joy hurts my head chaos be happy okay",
2074        "how about that Pullin the dragons tail prosperity mocking refreshing StephenHawking my bad",
2075        "boss quite beep beep study dang it population basket case",
2076        "hobnob no you cant employee jealousy one of the secret words are REMOTE lift uh huh are you deaf",
2077        "bickering skills thats laughable theres no place like home king of mars repeat after me go ahead make my day",
2078        "music you should be so lucky in theory no more tears do you know what time it is Angel it's hopeless",
2079        "couldnt possibly bad ol puddytat husband anger yep atheist et tu",
2080        "FBI energy lust well I never dance I'm the boss manufacturing",
2081        "think you could do better gluttony Shalom I didn't see that voodoo Han shot first how could you",
2082        "virtue experts just between us drama like like vengeance charity",
2083        "incredibly don't have a cow got the life Russia rufus! basically Is that so",
2084        "I planned that white trash failure to communicate check this out virtue crash and burn let's see",
2085        "check this out sloth news to me but of course NOT do it shucks",
2086        "It grieves me you're no fun cursing rufus! sess me rose colored glasses Church",
2087        "dance bizarre these cans are defective frown Knock you upside the head no more tears I am not amused",
2088        "manufacturing adjusted for inflation application Jedi mind trick do I have to praise Venus",
2089        "I'll let you know you're not all there are you I'm impressed talk to my lawyer abnormal This cant be william wallace frown",
2090        "Putin This cant be william wallace California rum bitty di end begs the question look buddy",
2091        "shist Greece failure to communicate you'll see rich left field Mom",
2092        "thats right you're wonderful you never know really that's your opinion what's up ice cream",
2093        "class  class  shutup tree hugger news to me just between us ROFLMAO not good not",
2094        "do it smile You fix it services liberal study I'm God and you're not",
2095        "chump change I'm feeling nice today thats just wrong you're fired it figures God smack Oy",
2096        "One finger salute ba ha won't you be my neighbor bring it on don't mention it talk to my lawyer exorbitant",
2097        "phasors on stun ohh thank you Yes you are how goes it nut job come and get me I got your back",
2098        "tattle tale you shouldn't have you're wonderful perfect Give me praise I veto that Is that so",
2099        "fabulous stuff pride Pope You know ordinarily ho ho ho",
2100        "ouch CIA study application phasors on stun not a chance in hell I'm not sure",
2101        "energy Isn't that special piety unsung hero guilty downer you owe me",
2102        "now you tell me no more hypocrite food one small step bad ol puddytat you're not all there are you",
2103        "depressing Ivy league I was just thinking umm I can't believe it ipod angel",
2104        "WooHoo place in theory strip African hello a flag on that play",
2105        "slumin grumble here now I'll get right on it frown If had my druthers over the top",
2106        "doh naughty joy NeilDeGrasseTyson sports nut job now you tell me",
2107        "commanded lust Yes you are don't worry recipe nope evolution",
2108        "manufacturing because I said so pride straighten up I'm on a roll quit it evolution",
2109        "Mom a likely story I'm off today Is that so don't mention it surprise surprise grumble",
2110        "arrogant won't you be my neighbor exports act yep Terry I have an idea",
2111        "reverse engineer I could be wrong news to me nope employee love foul",
2112        "conservative thank you very much commanded I'll let you know let me count the ways funny theres no place like home",
2113        "handyman yeah You get what you pray for whale gambling delightful sloth",
2114        "I'll think about it in theory awful Mom what a mess radio rum bitty di",
2115        "holy grail glam fortitude have fun depressing who are you to judge take your pick",
2116        "incoming in a galaxy far far away blessing spirit Pullin the dragons tail computers red fang",
2117        "beam me up Mom money boss fake prosperity scorning",
2118        "umm what now one more time nevada completely what's the plan rum bitty di no news is good news",
2119        "okay exorbitant hopefully mocking is it just me or I pity the fool that's your opinion",
2120        "because I said so kick back wot vote it's my world Pope charged",
2121        "money wazz up with that in other words I'm God who the hell are you tattle tale you're lucky don't count on it",
2122        "small talk genius lying here now mocking other smart",
2123        "you're lucky smurfs no way dude tree hugger abnormal You da man it's my world",
2124        "couldn't be better sloth look buddy we ve already got one holy grail take the day off ehheh that's all folks",
2125        "don't worry relax baffling whoop there it is phasors on stun lighten up I hate when that happens",
2126        "yeah illogical astrophysics not good busybody bye funny",
2127        "I hate when that happens food fancy it'd take a miracle shist pick me pick me sloth",
2128        "check this out wonderful ba ha Moses It's nice being God I don't care abnormal",
2129        "ipod here now one small step Ivy league that's your opinion you think I'm joking programming",
2130        "super computer happy GarryKasparov I be like smile God after a break",
2131        "Oh really it'd take a miracle nut job you owe me Pope holy grail dude such a scoffer",
2132        "genius humility California holier than thou persistence Isn't that special absetively posilutely",
2133        "desert break some woopass on you rufus! super computer stuff I'm thrilled the",
2134        "yep not too shabby voodoo you should be so lucky You da man boss Knock you upside the head",
2135        "joyful boss you're fired yada yada yada close your eyes look out you'll see",
2136        "Varoom food don't have a cow run away got the life You know stuff",
2137        "play is it just me or tiffanies vermin God is not mocked bad what luck",
2138        "by the way hotel pow study courage I can't believe it I pity the fool",
2139        "failure is not an option how hard could it be ridiculous what do you want nerd bring it on Dad",
2140        "spirit king of mars I'm off today threads oh oh what's the plan so he sess",
2141        "are you feeling lucky do not disturb here now bring it on Bam Dad red fang",
2142    ]);
2143    let mut joins = tokio::task::JoinSet::<ValidateResult>::new();
2144    let mut tasks = vec![];
2145    let views_url = Arc::new(views_url.clone());
2146    for i in 0..5 {
2147        let u = ws_base_url.clone();
2148        let ps = phrases.clone();
2149        let views_url = views_url.clone();
2150        let mut user = WS::new(test, format!("{}/19/ws/room/1/user/{}", u, i)).await?;
2151        tasks.push(async move {
2152            for (ii, p) in ps.iter().enumerate() {
2153                user.send_tweet(*p).await?;
2154                sleep(Duration::from_millis(150)).await;
2155                if i == 0 && ii == 50 {
2156                    let client = new_client();
2157                    client
2158                        .get(views_url.deref())
2159                        .send()
2160                        .await
2161                        .map_err(|_| test)?;
2162                }
2163            }
2164            sleep(Duration::from_secs(2)).await;
2165            user.close().await?;
2166
2167            Ok(())
2168        });
2169    }
2170    for t in tasks.into_iter() {
2171        joins.spawn(t);
2172    }
2173    while let Some(Ok(r)) = joins.join_next().await {
2174        r?;
2175    }
2176    sleep(Duration::from_millis(100)).await;
2177    ensure_views(2500).await.map_err(|_| test)?;
2178    // TASK 2 DONE
2179    tx.send((false, 500).into()).await.unwrap();
2180
2181    Ok(())
2182}
2183
2184async fn validate_20(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
2185    let client = new_client();
2186    let mut test: TaskTest;
2187    // TASK 1
2188    test = (1, 1);
2189    let url = &format!("{}/20/archive_files", base_url);
2190    let res = client
2191        .post(url)
2192        .body(include_bytes!("../assets/northpole20231220.tar").to_vec())
2193        .send()
2194        .await
2195        .map_err(|_| test)?;
2196    let text = res.text().await.map_err(|_| test)?;
2197    if text != "6" {
2198        return Err(test);
2199    }
2200    test = (1, 2);
2201    let url = &format!("{}/20/archive_files_size", base_url);
2202    let res = client
2203        .post(url)
2204        .body(include_bytes!("../assets/northpole20231220.tar").to_vec())
2205        .send()
2206        .await
2207        .map_err(|_| test)?;
2208    let text = res.text().await.map_err(|_| test)?;
2209    if text != "1196282" {
2210        return Err(test);
2211    }
2212    // TASK 1 DONE
2213    tx.send((true, 0).into()).await.unwrap();
2214    tx.send(SubmissionUpdate::Save).await.unwrap();
2215
2216    // TASK 2
2217    test = (2, 1);
2218    let url = &format!("{}/20/cookie", base_url);
2219    let res = client
2220        .post(url)
2221        .body(include_bytes!("../assets/cookiejar.tar").to_vec())
2222        .send()
2223        .await
2224        .map_err(|_| test)?;
2225    let text = res.text().await.map_err(|_| test)?;
2226    if text != "Grinch 71dfab551a1958b35b7436c54b7455dcec99a12c" {
2227        return Err(test);
2228    }
2229    test = (2, 2);
2230    let url = &format!("{}/20/cookie", base_url);
2231    let res = client
2232        .post(url)
2233        .body(include_bytes!("../assets/lottery.tar").to_vec())
2234        .send()
2235        .await
2236        .map_err(|_| test)?;
2237    let text = res.text().await.map_err(|_| test)?;
2238    if text != "elf-27221 6342c1dbdb560f0d5dcaac7566fca51454866664" {
2239        return Err(test);
2240    }
2241    // TASK 2 DONE
2242    tx.send((false, 350).into()).await.unwrap();
2243
2244    Ok(())
2245}
2246
2247async fn validate_21(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
2248    let client = new_client();
2249    let mut test: TaskTest;
2250    // TASK 1
2251    test = (1, 1);
2252    let url = &format!(
2253        "{}/21/coords/0100111110010011000110011001010101011111000010100011110001011011",
2254        base_url
2255    );
2256    let res = client.get(url).send().await.map_err(|_| test)?;
2257    let text = res.text().await.map_err(|_| test)?;
2258    if text != "83°39'54.324''N 30°37'40.584''W" {
2259        return Err(test);
2260    }
2261    test = (1, 2);
2262    let url = &format!(
2263        "{}/21/coords/0010000111110000011111100000111010111100000100111101111011000101",
2264        base_url
2265    );
2266    let res = client.get(url).send().await.map_err(|_| test)?;
2267    let text = res.text().await.map_err(|_| test)?;
2268    if text != "18°54'55.944''S 47°31'17.976''E" {
2269        return Err(test);
2270    }
2271    test = (1, 3);
2272    let url = &format!(
2273        "{}/21/coords/0101110100010001110001111100100111000111100010111100111101110001",
2274        base_url
2275    );
2276    let res = client.get(url).send().await.map_err(|_| test)?;
2277    let text = res.text().await.map_err(|_| test)?;
2278    if text != "51°26'57.804''N 99°28'33.204''E" {
2279        return Err(test);
2280    }
2281    // TASK 1 DONE
2282    tx.send((true, 0).into()).await.unwrap();
2283    tx.send(SubmissionUpdate::Save).await.unwrap();
2284
2285    // TASK 2
2286    test = (2, 1);
2287    let url = &format!(
2288        "{}/21/country/0010000111110000011111100000111010111100000100111101111011000101",
2289        base_url
2290    );
2291    let res = client.get(url).send().await.map_err(|_| test)?;
2292    let text = res.text().await.map_err(|_| test)?;
2293    if text != "Madagascar" {
2294        return Err(test);
2295    }
2296    test = (2, 2);
2297    let url = &format!(
2298        "{}/21/country/0011001000100010100010110001110100000111000010111000100000010101",
2299        base_url
2300    );
2301    let res = client.get(url).send().await.map_err(|_| test)?;
2302    let text = res.text().await.map_err(|_| test)?;
2303    if text != "Brunei" {
2304        return Err(test);
2305    }
2306    test = (2, 3);
2307    let url = &format!(
2308        "{}/21/country/1001010011001110010011100110001000100110100111001001000100110001",
2309        base_url
2310    );
2311    let res = client.get(url).send().await.map_err(|_| test)?;
2312    let text = res.text().await.map_err(|_| test)?;
2313    if text != "Brazil" {
2314        return Err(test);
2315    }
2316    test = (2, 4);
2317    let url = &format!(
2318        "{}/21/country/0101110100010001110001111100100111000111100010111100111101110001",
2319        base_url
2320    );
2321    let res = client.get(url).send().await.map_err(|_| test)?;
2322    let text = res.text().await.map_err(|_| test)?;
2323    if text != "Mongolia" {
2324        return Err(test);
2325    }
2326    test = (2, 5);
2327    let url = &format!(
2328        "{}/21/country/0011100111101001000010001100001100111111101001100110000010101011",
2329        base_url
2330    );
2331    let res = client.get(url).send().await.map_err(|_| test)?;
2332    let text = res.text().await.map_err(|_| test)?;
2333    if text != "Nepal" {
2334        return Err(test);
2335    }
2336    test = (2, 6);
2337    let url = &format!(
2338        "{}/21/country/0100011111000110101110101100011001101001111111001011000011101111",
2339        base_url
2340    );
2341    let res = client.get(url).send().await.map_err(|_| test)?;
2342    let text = res.text().await.map_err(|_| test)?;
2343    if text != "Belgium" {
2344        return Err(test);
2345    }
2346    test = (2, 7);
2347    let url = &format!(
2348        "{}/21/country/0100111100110010101001010001010100100110110000100100101011011111",
2349        base_url
2350    );
2351    let res = client.get(url).send().await.map_err(|_| test)?;
2352    let text = res.text().await.map_err(|_| test)?;
2353    if text != "Iceland" {
2354        return Err(test);
2355    }
2356    // TASK 2 DONE
2357    tx.send((false, 300).into()).await.unwrap();
2358
2359    Ok(())
2360}
2361
2362struct TextTester {
2363    client: reqwest::Client,
2364    url: String,
2365}
2366
2367impl TextTester {
2368    fn new(url: String) -> Self {
2369        Self {
2370            client: new_client(),
2371            url,
2372        }
2373    }
2374    async fn test(&self, test: TaskTest, i: &str, code: StatusCode, o: &str) -> ValidateResult {
2375        let res = self
2376            .client
2377            .post(&self.url)
2378            .body(i.to_owned())
2379            .send()
2380            .await
2381            .map_err(|_| test)?;
2382        if res.status() != code {
2383            return Err(test);
2384        }
2385        let text = res.text().await.map_err(|_| test)?;
2386        if text != o {
2387            return Err(test);
2388        }
2389        Ok(())
2390    }
2391}
2392
2393async fn validate_22(base_url: &str, tx: Sender<SubmissionUpdate>) -> ValidateResult {
2394    // TASK 1
2395    let t = TextTester::new(format!("{}/22/integers", base_url));
2396    t.test(
2397        (1, 1),
2398        "\
23991
2400",
2401        StatusCode::OK,
2402        "🎁",
2403    )
2404    .await?;
2405    t.test(
2406        (1, 2),
2407        "\
24081
24091
24102
24112
24123
24133
24144
2415",
2416        StatusCode::OK,
2417        "🎁".repeat(4).as_str(),
2418    )
2419    .await?;
2420    t.test(
2421        (1, 3),
2422        "\
24231
24243
24251
24262
24274
24282
24293
2430",
2431        StatusCode::OK,
2432        "🎁".repeat(4).as_str(),
2433    )
2434    .await?;
2435    t.test(
2436        (1, 4),
2437        "\
243811111111111111111111
2439555555555555555
244033333333
244168
2442555555555555555
244333333333
24444444
244511111111111111111111
24464444
2447",
2448        StatusCode::OK,
2449        "🎁".repeat(68).as_str(),
2450    )
2451    .await?;
2452    t.test(
2453        (1, 5),
2454        include_str!("../assets/numbers.txt"),
2455        StatusCode::OK,
2456        "🎁".repeat(120003).as_str(),
2457    )
2458    .await?;
2459    // TASK 1 DONE
2460    tx.send((true, 0).into()).await.unwrap();
2461    tx.send(SubmissionUpdate::Save).await.unwrap();
2462
2463    // TASK 2
2464    let t = TextTester::new(format!("{}/22/rocket", base_url));
2465    t.test(
2466        (2, 1),
2467        "\
24682
24690 0 0
24700 0 1
24711
24720 1
2473",
2474        StatusCode::OK,
2475        "1 1.000",
2476    )
2477    .await?;
2478    t.test(
2479        (2, 2),
2480        "\
24815
24820 1 0
2483-2 2 3
24843 -3 -5
24851 1 5
24864 3 5
24874
24880 1
24892 4
24903 4
24911 2
2492",
2493        StatusCode::OK,
2494        "3 26.123",
2495    )
2496    .await?;
2497    t.test(
2498        (2, 3),
2499        "\
25005
25010 1 0
2502-2 2 3
25033 -3 -5
25041 1 5
25054 3 5
25065
25070 1
25081 3
25093 4
25100 2
25112 4
2512",
2513        StatusCode::OK,
2514        "2 18.776",
2515    )
2516    .await?;
2517    t.test(
2518        (2, 4),
2519        "\
25205
25210 1 0
2522-2 2 3
25233 -3 -5
25241 1 5
25254 3 5
25261
25270 4
2528",
2529        StatusCode::OK,
2530        "1 6.708",
2531    )
2532    .await?;
2533    t.test(
2534        (2, 5),
2535        "\
25365
25370 1 0
2538-2 2 3
25393 -3 -5
25401 1 5
25414 3 5
25425
25430 4
25440 1
25451 2
25462 0
25470 3
2548",
2549        StatusCode::OK,
2550        "1 6.708",
2551    )
2552    .await?;
2553    t.test(
2554        (2, 6),
2555        "\
255621
2557570 -435 923
2558672 -762 -218
2559707 16 640
2560311 902 47
2561-963 -399 -773
2562788 532 -704
2563703 475 -145
2564-303 -394 -369
2565699 -640 952
2566-341 -221 743
2567740 -146 544
2568-424 655 179
2569-630 161 690
2570789 -848 -517
2571-14 -893 551
2572-48 815 962
2573528 552 -96
2574337 983 165
2575-565 459 -90
257681 -476 301
2577-685 -319 698
257824
25790 2
25802 4
25814 6
25826 10
258310 17
258417 20
258520 18
258618 11
258711 7
25887 5
25895 3
25903 0
25910 1
25921 12
259312 13
259413 19
259519 20
259620 16
259716 14
259814 15
259915 9
26009 8
26018 6
260211 16
2603",
2604        StatusCode::OK,
2605        "5 7167.055",
2606    )
2607    .await?;
2608    t.test(
2609        (2, 7),
2610        "\
261175
2612570 -435 923
2613672 -762 -218
2614707 16 640
2615311 902 47
2616-963 -399 -773
2617788 532 -704
2618703 475 -145
2619-303 -394 -369
2620699 -640 952
2621-341 -221 743
2622740 -146 544
2623-424 655 179
2624-630 161 690
2625789 -848 -517
2626-14 -893 551
2627-48 815 962
2628528 552 -96
2629337 983 165
2630-565 459 -90
263181 -476 301
2632-685 -319 698
2633-264 96 361
2634796 94 402
2635983 763 -953
2636711 -221 -866
2637-578 128 -178
2638-464 117 304
2639426 -433 -961
2640-626 -779 -596
2641-117 -88 349
2642880 -286 -527
2643941 -451 177
2644627 -832 286
2645593 370 -436
2646609 431 -681
2647-549 -690 447
2648957 849 -162
2649189 290 -485
2650-914 -447 -61
2651367 731 825
2652-177 432 -675
2653-926 -811 198
2654-379 345 831
2655-669 -134 804
2656956 380 -427
2657213 -954 -357
2658-806 -663 583
26597 -460 374
2660-384 -797 -404
2661-793 -333 196
2662402 175 329
2663703 9 -926
2664599 559 -844
266564 343 885
2666-865 -49 -373
2667-728 880 -164
2668830 528 -394
2669931 -782 -365
2670661 -528 931
2671-764 34 -289
2672442 298 983
2673-899 382 -967
2674662 361 -85
2675775 98 -519
2676202 335 60
2677474 823 -677
2678-708 41 127
2679-974 718 81
2680443 -526 -945
2681-279 778 -271
2682896 26 -902
2683-977 -233 837
2684151 -22 -454
2685824 -472 471
2686702 871 -244
268773
26880 1
26890 2
26900 4
26910 5
26920 7
26931 10
269410 11
269511 25
269612 13
269713 27
269814 29
269915 30
270016 17
270117 35
270218 36
270319 6
27042 3
270520 22
270621 19
270722 40
270823 60
270924 42
271025 26
271126 43
271227 28
271328 45
271429 47
27153 12
271630 31
271731 68
271832 50
271934 16
272035 52
272136 54
272237 38
272338 57
272439 21
27254 14
272640 59
272741 23
272842 61
272943 44
273044 63
273145 64
273246 65
273347 46
273449 32
273549 68
27365 15
273750 33
273851 34
273952 70
274054 73
274155 37
274256 74
274357 56
274458 39
274559 58
27466 18
274763 62
274865 66
274966 67
275067 48
275169 51
27527 20
275370 71
275471 72
275572 53
275673 55
27578 1
27588 9
27599 23
27609 24
2761",
2762        StatusCode::OK,
2763        "20 27826.439",
2764    )
2765    .await?;
2766    t.test(
2767        (2, 8),
2768        "\
276970
2770788 532 -704
2771703 475 -145
2772-303 -394 -369
2773699 -640 952
2774-341 -221 743
2775740 -146 544
2776-424 655 179
2777-630 161 690
2778789 -848 -517
2779-14 -893 551
2780-48 815 962
2781528 552 -96
2782337 983 165
2783-565 459 -90
278481 -476 301
2785-685 -319 698
2786-264 96 361
2787796 94 402
2788983 763 -953
2789711 -221 -866
2790-578 128 -178
2791-464 117 304
2792426 -433 -961
2793-626 -779 -596
2794-117 -88 349
2795880 -286 -527
2796941 -451 177
2797627 -832 286
2798593 370 -436
2799609 431 -681
2800-549 -690 447
2801957 849 -162
2802189 290 -485
2803-914 -447 -61
2804367 731 825
2805-177 432 -675
2806-926 -811 198
2807-379 345 831
2808-669 -134 804
2809956 380 -427
2810213 -954 -357
2811-806 -663 583
28127 -460 374
2813-384 -797 -404
2814-793 -333 196
2815402 175 329
2816703 9 -926
2817599 559 -844
281864 343 885
2819-865 -49 -373
2820-728 880 -164
2821830 528 -394
2822931 -782 -365
2823661 -528 931
2824-764 34 -289
2825442 298 983
2826-899 382 -967
2827662 361 -85
2828775 98 -519
2829202 335 60
2830474 823 -677
2831-708 41 127
2832-974 718 81
2833443 -526 -945
2834-279 778 -271
2835896 26 -902
2836-977 -233 837
2837151 -22 -454
2838824 -472 471
2839702 871 -244
284070
28410 10
28420 2
28430 3
28441 22
284510 21
284611 1
284712 11
284813 27
284914 15
285015 4
285116 31
285217 33
285318 19
285419 7
28552 12
285620 53
285721 37
285822 39
285923 40
286024 23
286125 24
286226 25
286327 26
286427 6
286528 14
286629 30
28673 13
286830 46
286930 69
287031 47
287133 18
287233 48
287334 33
287435 34
287537 20
287638 55
287739 56
287839 57
28794 16
288040 59
288141 60
288242 62
288343 63
288444 28
288544 65
288645 29
288746 68
288847 32
288948 49
289049 50
28915 17
289250 51
289351 35
289453 36
289555 54
289656 38
289757 58
289859 41
28996 5
290060 61
290161 42
290262 43
290363 64
290464 44
290565 45
290667 66
290768 67
29087 9
29098 0
29109 8
2911",
2912        StatusCode::OK,
2913        "23 34029.320",
2914    )
2915    .await?;
2916    // TASK 2 DONE
2917    tx.send((false, 600).into()).await.unwrap();
2918
2919    Ok(())
2920}