aboutsummaryrefslogtreecommitdiff
path: root/planetwars-matchrunner/src/bin/testmatch.rs
blob: 97c00edd3bf44f21459c246c22fc5c97a785ae77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
extern crate planetwars_matchrunner;
extern crate tokio;

use std::collections::HashMap;
use std::io::{self, Write};
use std::path::PathBuf;
use std::pin::Pin;
use std::sync::{Arc, Mutex};

use bollard::container::{self, LogOutput};
use bollard::exec::StartExecResults;
use bollard::Docker;
use futures::{Stream, StreamExt};
use planetwars_matchrunner::{
    match_context::{EventBus, MatchCtx, PlayerHandle},
    pw_match, MatchConfig, MatchMeta, PlayerInfo,
};
use planetwars_rules::protocol as proto;
use planetwars_rules::PwConfig;
use std::env;
use tokio::io::{AsyncWrite, AsyncWriteExt};

const IMAGE: &'static str = "simplebot:latest";

#[tokio::main]
async fn main() {
    let args: Vec<String> = env::args().collect();
    assert!(args.len() >= 2);
    let map_path = args[1].clone();
    _run_match(map_path).await;
}

async fn _run_match(map_path: String) {
    let docker = Docker::connect_with_socket_defaults().unwrap();
    create_player_process(&docker).await.unwrap();
}

async fn create_player_process(docker: &Docker) -> Result<(), bollard::errors::Error> {
    let config = container::Config {
        image: Some(IMAGE),
        ..Default::default()
    };

    let response = docker.create_container::<&str, &str>(None, config).await?;
    let container_id = response.id;

    docker
        .start_container::<String>(&container_id, None)
        .await?;

    let exec_id = docker
        .create_exec::<&str>(
            &container_id,
            bollard::exec::CreateExecOptions {
                attach_stdin: Some(true),
                attach_stdout: Some(true),
                attach_stderr: Some(true),
                cmd: Some(vec!["python", "simplebot.py"]),
                ..Default::default()
            },
        )
        .await
        .unwrap()
        .id;

    let start_exec_results = docker.start_exec(&exec_id, None).await?;
    let (mut input, mut output) = match start_exec_results {
        StartExecResults::Detached => panic!("failed to get io channels"),
        StartExecResults::Attached { input, output } => (input, output),
    };

    let state = proto::State {
        planets: vec![
            proto::Planet {
                name: "a".to_string(),
                owner: Some(1),
                ship_count: 100,
                x: -1.0,
                y: 0.0,
            },
            proto::Planet {
                name: "b".to_string(),
                owner: Some(2),
                ship_count: 100,
                x: 1.0,
                y: 0.0,
            },
        ],
        expeditions: vec![],
    };

    let serialized = serde_json::to_vec(&state).unwrap();
    input.write_all(&serialized).await?;
    input.write(b"\n").await?;
    input.flush().await?;

    while let Some(item) = output.next().await {
        let log_output = item.expect("failed to get log output");
        match log_output {
            LogOutput::StdOut { message } => {
                println!("stdout: {}", String::from_utf8_lossy(&message));
            }
            LogOutput::StdErr { message } => {
                println!("stderr: {}", String::from_utf8_lossy(&message));
            }
            _ => (),
        }
    }

    Ok(())
}