]> git.seodisparate.com - EN605.607.81.SP22_ASDM_Project/commitdiff
back-end: Impl "phrase", update protocol
authorStephen Seo <seo.disparate@gmail.com>
Wed, 27 Apr 2022 02:42:28 +0000 (11:42 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 27 Apr 2022 02:42:28 +0000 (11:42 +0900)
back_end/src/db_handler.rs
back_end/src/json_handlers.rs
specifications/backend_protocol_specification.md

index dea6fad180cbc5d78ebd0bd3cff92dea7f0ed63d..c7183094c4815ff62a35f90a025afe000e6e3234 100644 (file)
@@ -13,6 +13,7 @@ use crate::constants::{
 };
 use crate::state::{board_from_string, new_string_board, string_from_board, BoardState, Turn};
 
+use std::collections::HashMap;
 use std::sync::mpsc::{Receiver, RecvTimeoutError, SyncSender};
 use std::time::{Duration, Instant};
 use std::{fmt, thread};
@@ -118,7 +119,10 @@ impl fmt::Display for DBPlaceError {
 
 #[derive(Clone, Debug)]
 pub enum DBHandlerRequest {
-    GetID(SyncSender<GetIDSenderType>),
+    GetID {
+        response_sender: SyncSender<GetIDSenderType>,
+        phrase: Option<String>,
+    },
     CheckPairing {
         id: u32,
         response_sender: SyncSender<CheckPairingType>,
@@ -163,7 +167,10 @@ impl DBHandler {
         }
         let db_request = rx_recv_result.unwrap();
         match db_request {
-            DBHandlerRequest::GetID(player_tx) => {
+            DBHandlerRequest::GetID {
+                response_sender,
+                phrase,
+            } => {
                 // got request to create new player, create new player
                 let conn_result = self.get_conn(DBFirstRun::NotFirstRun);
                 if let Err(e) = conn_result {
@@ -172,10 +179,10 @@ impl DBHandler {
                 }
                 let conn = conn_result.unwrap();
 
-                let create_player_result = self.create_new_player(Some(&conn));
+                let create_player_result = self.create_new_player(Some(&conn), phrase);
                 if let Err(e) = create_player_result {
                     println!("{}", e);
-                    player_tx.send((None, None)).ok();
+                    response_sender.send((None, None)).ok();
                     // don't stop server because player limit may have been reached
                     return false;
                 }
@@ -197,11 +204,11 @@ impl DBHandler {
                         if paired {
                             // don't stop server on send fail, may have timed
                             // out and dropped the receiver
-                            player_tx.send((Some(player_id), Some(is_cyan))).ok();
+                            response_sender.send((Some(player_id), Some(is_cyan))).ok();
                         } else {
                             // don't stop server on send fail, may have timed
                             // out and dropped the receiver
-                            player_tx.send((Some(player_id), None)).ok();
+                            response_sender.send((Some(player_id), None)).ok();
                         }
                     } else {
                         println!("Internal error, created player doesn't exist");
@@ -341,7 +348,11 @@ impl DBHandler {
         Ok(())
     }
 
-    fn create_new_player(&self, conn: Option<&Connection>) -> Result<u32, String> {
+    fn create_new_player(
+        &self,
+        conn: Option<&Connection>,
+        phrase: Option<String>,
+    ) -> Result<u32, String> {
         let mut _conn_result = Err(String::new());
         let conn = if conn.is_none() {
             _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
@@ -380,7 +391,10 @@ impl DBHandler {
             }
         }
 
-        let insert_result = conn.execute("INSERT INTO players (id) VALUES (?);", [player_id]);
+        let insert_result = conn.execute(
+            "INSERT INTO players (id, phrase) VALUES (?, ?);",
+            params![player_id, phrase],
+        );
         if let Err(e) = insert_result {
             return Err(format!("Failed to insert player into db: {:?}", e));
         }
@@ -399,23 +413,39 @@ impl DBHandler {
 
         let mut to_pair: Option<u32> = None;
         let mut unpaired_players_stmt = conn
-            .prepare("SELECT id FROM players WHERE game_id ISNULL ORDER BY date_added;")
+            .prepare("SELECT id, phrase FROM players WHERE game_id ISNULL ORDER BY date_added;")
             .map_err(|e| format!("{:?}", e))?;
         let mut unpaired_players_rows = unpaired_players_stmt
             .query([])
             .map_err(|e| format!("{:?}", e))?;
+        let mut phrase_map: HashMap<String, u32> = HashMap::new();
         while let Some(row) = unpaired_players_rows
             .next()
             .map_err(|e| format!("{:?}", e))?
         {
-            if to_pair.is_none() {
-                to_pair = Some(row.get(0).map_err(|e| format!("{:?}", e))?);
+            if let Ok(phrase_text) = row.get::<usize, String>(1) {
+                // pair players with matching phrases
+                if let Some(matching_player_id) = phrase_map.get(&phrase_text) {
+                    let players: [u32; 2] = [
+                        *matching_player_id,
+                        row.get(0).map_err(|e| format!("{:?}", e))?,
+                    ];
+                    self.create_game(Some(conn), &players)?;
+                    phrase_map.remove(&phrase_text);
+                } else {
+                    phrase_map.insert(phrase_text, row.get(0).map_err(|e| format!("{:?}", e))?);
+                }
             } else {
-                let players: [u32; 2] = [
-                    to_pair.take().unwrap(),
-                    row.get(0).map_err(|e| format!("{:?}", e))?,
-                ];
-                self.create_game(Some(conn), &players)?;
+                // pair players that did not use a phrase
+                if to_pair.is_none() {
+                    to_pair = Some(row.get(0).map_err(|e| format!("{:?}", e))?);
+                } else {
+                    let players: [u32; 2] = [
+                        to_pair.take().unwrap(),
+                        row.get(0).map_err(|e| format!("{:?}", e))?,
+                    ];
+                    self.create_game(Some(conn), &players)?;
+                }
             }
         }
 
index f7249b1aa1a8aed8c75fb65534856aa37d21ce8b..0f4c1df7d864646160e09cebb98488c5659b2243 100644 (file)
@@ -24,7 +24,7 @@ pub fn handle_json(
 ) -> Result<String, String> {
     if let Some(Value::String(type_str)) = root.get("type") {
         match type_str.as_str() {
-            "pairing_request" => handle_pairing_request(tx),
+            "pairing_request" => handle_pairing_request(root, tx),
             "check_pairing" => handle_check_pairing(root, tx),
             "place_token" => handle_place_token(root, tx),
             "disconnect" => handle_disconnect(root, tx),
@@ -36,9 +36,21 @@ pub fn handle_json(
     }
 }
 
-fn handle_pairing_request(tx: SyncSender<DBHandlerRequest>) -> Result<String, String> {
+fn handle_pairing_request(root: Value, tx: SyncSender<DBHandlerRequest>) -> Result<String, String> {
     let (player_tx, player_rx) = sync_channel::<GetIDSenderType>(1);
-    if tx.send(DBHandlerRequest::GetID(player_tx)).is_err() {
+    let mut phrase: Option<String> = None;
+    if let Some(phrase_text) = root.get("phrase") {
+        if let Some(phrase_str) = phrase_text.as_str() {
+            phrase = Some(phrase_str.to_owned());
+        }
+    }
+    if tx
+        .send(DBHandlerRequest::GetID {
+            response_sender: player_tx,
+            phrase,
+        })
+        .is_err()
+    {
         return Err("{\"type\":\"pairing_response\", \"status\":\"internal_error\"}".into());
     }
     if let Ok((pid_opt, is_cyan_opt)) = player_rx.recv_timeout(DB_REQUEST_TIMEOUT) {
index 19885d2ee265d754f770c0005b1eebfb9c2d2308..aee257aebd8699be454fbd13887c64f59b39b1fa 100644 (file)
@@ -14,6 +14,15 @@ of the request, and the backend will respond with JSON.
     }
 ```
 
+An optional "phrase" parameter can be sent to match against other players with
+the same "phrase".
+```
+    {
+        "type": "pairing_request",
+        "phrase": "user_defined_phrase",
+    }
+```
+
 2. Check pairing status
 
 ```