diff --git a/Makefile b/Makefile
index 55a55806cd470b372e48aec68d7b64052dd4b416..9dba7ae7834112d446a698974bca2150fc588b0a 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC     = gcc
 CFLAGS = -Wall -std=c99 -g
 # modify the flags here ^
 EXE    = image_tagger
-OBJ    = hashtable.o http-parser.o http-response.o http-server.o
+OBJ    = hashtable.o user.o http-parser.o http-response.o http-server.o
 # add any new object files here ^
 # top (default) target
 all: $(EXE)
@@ -14,7 +14,7 @@ $(EXE): $(OBJ)
 # other dependencies
 http-parser.o: http-parser.h hashtable.h
 http-response.o: http-response.h http-parser.h hashtable.h
-http-server.o: http-parser.h
+http-server.o: http-parser.h user.h
 
 # ^ add any new dependencies here (for example if you add new modules)
 
diff --git a/hashtable.o b/hashtable.o
new file mode 100644
index 0000000000000000000000000000000000000000..3d009356e879e27341f185114559a9f4dd7c78e1
Binary files /dev/null and b/hashtable.o differ
diff --git a/http-parser.c b/http-parser.c
index 92ac25cc6ef188883581e85713dd7659d90c20ed..ddbe63198e8c37fa69cf45de4777fcc006ca7a30 100644
--- a/http-parser.c
+++ b/http-parser.c
@@ -33,7 +33,7 @@ Request* parse_request(char* request_message){
     char header_field_name[MAX_HEADER_SIZE];
     char header_value[MAX_HEADER_SIZE];
     while(*request_message != '\r' && *request_message != '\n'){
-        printf("req message first char %d\n", *request_message);
+       printf("req message first char %d\n", *request_message);
        strcpy(header_field_name,strtok(request_message, " "));
        printf("header field name: %s\n", header_field_name);
        request_message += strcspn(request_message, " ")+1;
@@ -42,6 +42,7 @@ Request* parse_request(char* request_message){
        request_message += strcspn(request_message, "\r\n")+2;
        hash_table_put(req->header, header_field_name, header_value);
     }
+    request_message += strcspn(request_message, "\r\n")+2;
     if(*request_message != '\r'||*request_message != '\n'){
         req->body = request_message;
     }
diff --git a/http-parser.o b/http-parser.o
new file mode 100644
index 0000000000000000000000000000000000000000..988eedd96577d49a833768472065914ea30d7f3d
Binary files /dev/null and b/http-parser.o differ
diff --git a/http-response.c b/http-response.c
index feaf292603afbc30744710008a4b438cf1701840..e7d1846a81d4d15fee6f9cfa70e987d7befe05d1 100644
--- a/http-response.c
+++ b/http-response.c
@@ -11,10 +11,37 @@
 #define MAX_HEADER_SIZE 300
 #define MAX_VERSION_SIZE 10
 
-Response* redirect(Request* request_message){
-    
+Response* redirect(Request* request, char* url_string){
+    Response *resp = malloc(sizeof *resp);
+	assert(resp);
+    resp->status_code=303;
+    resp->version = request->version;
+    resp->phrase = "Moved Permanently";
+    resp->header = new_hash_table(2);
+    hash_table_put(resp->header, "Location:", url_string);
+    resp->body="";
+    return resp;
 }
 
+char* parse_response(Response* response){
+    char* response_string;
+    char int_buff[4];
+    response_string = (char *) malloc(sizeof(char)*100);
+    strcat(response_string, response->version);
+    strcat(response_string," ");
+    sprintf(int_buff, "%d", response->status_code);
+    strcat(response_string, int_buff);
+    strcat(response_string, " ");
+    strcat(response_string, response->phrase);
+    strcat(response_string, "\r\n");
+    strcat(response_string, "Location: ");
+    strcat(response_string,hash_table_get(response->header, "Location:"));
+    strcat(response_string, "\r\n\r\n");
+    strcat(response_string, response->body);
+    return response_string;
+}
+
+
 void free_response(Response* resp){
     free_hash_table(resp->header);
     free(resp);
diff --git a/http-response.h b/http-response.h
index 7fdf1ba387488577bb7dd9c36a53da5958f09c72..14216960f9b3b79fd55e27754df6289cb1fd8060 100644
--- a/http-response.h
+++ b/http-response.h
@@ -11,4 +11,6 @@ typedef struct Response {
 
 
 //Creates a new hash table of input size
-Response *redirect(Request *req);
\ No newline at end of file
+Response *redirect(Request *req, char* url_string);
+
+char* parse_response(Response* response);
\ No newline at end of file
diff --git a/http-response.o b/http-response.o
new file mode 100644
index 0000000000000000000000000000000000000000..5ab883eb71fd341af4e8733938c009aefa145748
Binary files /dev/null and b/http-response.o differ
diff --git a/http-server b/http-server
new file mode 100644
index 0000000000000000000000000000000000000000..763fea59bb89bfd22a8d3b5633e585be3bf457cc
Binary files /dev/null and b/http-server differ
diff --git a/http-server.c b/http-server.c
index e215827f4c4e07f8e621c69beb2adbc21292ade9..9b7244d877a37da75eaeef420ce149bab2727978 100644
--- a/http-server.c
+++ b/http-server.c
@@ -20,6 +20,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include "http-parser.h"
+#include "http-response.h"
+#include "user.h"
 
 // constants
 static char const * const HTTP_200_FORMAT = "HTTP/1.1 200 OK\r\n\
@@ -60,56 +62,57 @@ bool get_request(char* buff, int sockfd, char* file_name){
     return true;
 }
 
-bool post_request(char *buff, int sockfd, char* file_name){
+bool post_request(char *buff, int sockfd, char* file_name, char* response){
 	// locate the username, it is safe to do so in this sample code, but usually the result is expected to be
-            // copied to another buffer using strcpy or strncpy to ensure that it will not be overwritten.
-            char * username = strcpy(buff, "user=") + 5;
-            int username_length = strlen(username);
-            // the length needs to include the ", " before the username
-            long added_length = username_length + 2;
+    // copied to another buffer using strcpy or strncpy to ensure that it will not be overwritten.
+    printf("USERNAME IS %s\n\n", buff);
+    char * username = strcpy(buff, "user=") + 5;
+    int username_length = strlen(username);
+    // the length needs to include the ", " before the username
+    long added_length = username_length + 2;
 
-            // get the size of the file
-            struct stat st;
-            stat(file_name, &st);
-            // increase file size to accommodate the username
-            long size = st.st_size + added_length;
-            int n = sprintf(buff, HTTP_200_FORMAT, size);
-            // send the header first
-            if (write(sockfd, buff, n) < 0)
-            {
-                perror("write");
-                return false;
-            }
-            // read the content of the HTML file
-            int filefd = open(file_name, O_RDONLY);
-            n = read(filefd, buff, 2048);
-            if (n < 0)
-            {
-                perror("read");
-                close(filefd);
-                return false;
-            }
-            close(filefd);
-            // move the trailing part backward
-            int p1, p2;
-            for (p1 = size - 1, p2 = p1 - added_length; p1 >= size - 25; --p1, --p2)
-                buff[p1] = buff[p2];
-            ++p2;
-            // put the separator
-            buff[p2++] = ',';
-            buff[p2++] = ' ';
-            // copy the username
-            strncpy(buff + p2, username, username_length);
-            if (write(sockfd, buff, size) < 0)
-            {
-                perror("write");
-                return false;
-            }
+    // get the size of the file
+    struct stat st;
+    stat(file_name, &st);
+    // increase file size to accommodate the username
+    long size = st.st_size + added_length;
+    int n = sprintf(buff, response, size);
+    // send the header first
+    if (write(sockfd, buff, n) < 0)
+    {
+        perror("write");
+        return false;
+    }
+    // read the content of the HTML file
+    int filefd = open(file_name, O_RDONLY);
+    n = read(filefd, buff, 2048);
+    if (n < 0)
+    {
+        perror("read");
+        close(filefd);
+        return false;
+    }
+    close(filefd);
+    // move the trailing part backward
+    int p1, p2;
+    for (p1 = size - 1, p2 = p1 - added_length; p1 >= size - 25; --p1, --p2)
+        buff[p1] = buff[p2];
+    ++p2;
+    // put the separator
+    buff[p2++] = ',';
+    buff[p2++] = ' ';
+    // copy the username
+    strncpy(buff + p2, username, username_length);
+    if (write(sockfd, buff, size) < 0)
+    {
+        perror("write");
+        return false;
+    }
 	return true;
 }
 
 
-static bool handle_http_request(int sockfd)
+static bool handle_http_request(int sockfd, User_list* users)
 {
     // try to read the request
     char buff[2049];
@@ -129,16 +132,37 @@ static bool handle_http_request(int sockfd)
     char * curr = buff;
 
     // parse the method
-    printf("cur is:      %s\n\n", curr);
     Request* req = parse_request(curr);
-    printf("%s\n%s\n", req->url, req->version);
-    if (strncmp(req->url, "?start=Start", 12)  == 0){
+    printf("REQUEST BODY IS \n\n%s\n", req->body);
+    if (strncmp(req->url, "/welcome_page?start=Start", 24)  == 0){
         printf("matches start");
         if (req->method == GET){
                 get_request(buff,sockfd, "3_first_turn.html");
         }
         if (req->method == POST){
-                post_request(buff,sockfd, "7_gameover.html");
+            Response* response = redirect(req, "gameover_page");
+            
+            char *resp = parse_response(response);
+		    post_request(buff,sockfd, "7_gameover.html",resp); 
+            free(response);
+        }
+    }
+    else if (strncmp(req->url, "/gameover_page", 14) == 0){
+        if(req->method == GET){
+            get_request(buff,sockfd, "7_gameover.html");
+            printf("i return false\n");
+        }
+    }
+    else if (strncmp(req->url, "/welcome_page", 13) == 0){
+        if(req->method == GET){
+            get_request(buff,sockfd, "2_start.html");
+        }
+        if (req->method == POST){
+            Response* response = redirect(req, "gameover_page");
+            
+            char *resp = parse_response(response);
+		    post_request(buff,sockfd, "7_gameover.html",resp); 
+            free(response);
         }
     }
     // assume the only valid request URI is "/" but it can be modified to accept more files
@@ -146,12 +170,24 @@ static bool handle_http_request(int sockfd)
     else if (*req->url == '/')
         if (req->method == GET)
         {
-            printf("%s\n", curr);
             get_request(buff,sockfd, "1_welcome.html");
         }
         else if (req->method == POST)
         {
-		post_request(buff,sockfd, "2_start.html");    
+            char *name = strchr(req->body, '=')+1;
+            printf("**%s**\n", name);
+            if (name != NULL){
+                // for (int i=0; i < users->n_users; i++){
+                //     if(users->users[i]->name == NULL){
+                //         users->users[i]->name = name;
+                //     }
+                // }
+                Response* response = redirect(req, "welcome_page");
+                char *resp = parse_response(response);
+                post_request(buff,sockfd, "2_start.html",resp); 
+                free(resp);
+                free(response);   
+            }
         }
         else
             // never used, just for completeness
@@ -215,7 +251,6 @@ int main(int argc, char * argv[])
     FD_SET(sockfd, &masterfds);
     // record the maximum socket number
     int maxfd = sockfd;
-
     while (1)
     {
         // monitor file descriptors
@@ -225,9 +260,9 @@ int main(int argc, char * argv[])
             perror("select");
             exit(EXIT_FAILURE);
         }
-
+        User_list* users = initialise_player_list();
         // loop all possible descriptor
-        for (int i = 0; i <= maxfd; ++i)
+        for (int i = 0; i <= maxfd; ++i){
             // determine if the current file descriptor is active
             if (FD_ISSET(i, &readfds))
             {
@@ -257,12 +292,14 @@ int main(int argc, char * argv[])
                     }
                 }
                 // a request is sent from the client
-                else if (!handle_http_request(i))
+                else if (!handle_http_request(i, users))
                 {
                     close(i);
                     FD_CLR(i, &masterfds);
                 }
             }
+        }
+    free(users);
     }
 
     return 0;
diff --git a/http-server.o b/http-server.o
new file mode 100644
index 0000000000000000000000000000000000000000..093df8e7e2a3ddabcd0698b5ad7665901308b55f
Binary files /dev/null and b/http-server.o differ
diff --git a/image_tagger b/image_tagger
new file mode 100644
index 0000000000000000000000000000000000000000..0032bce3a0d8b40dcdcd0f00cb256e60db02cc9b
Binary files /dev/null and b/image_tagger differ
diff --git a/server b/server
new file mode 100644
index 0000000000000000000000000000000000000000..c63bbc29bdba00c9da7a64d718dba72f1c414565
Binary files /dev/null and b/server differ
diff --git a/user.c b/user.c
new file mode 100644
index 0000000000000000000000000000000000000000..169b93d63077a772f1679600cef0b9fc923a67ad
--- /dev/null
+++ b/user.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "user.h"
+
+
+User* new_user(){
+    User *user = malloc(sizeof(User*));
+    assert(user);
+    user->n_capacity = 5;
+    user->n_keywords = 0;
+    user->status = WAIT;
+    user->keywords = malloc(sizeof(char*)*user->n_capacity);
+    assert(user->keywords);
+    return user;
+}
+
+User_list* initialise_player_list(){
+    User_list *users = malloc(sizeof(User_list));
+    assert(users);
+    users->n_users = 0;
+    users->users = malloc(sizeof(User*)*3);
+    assert(users->users);
+    return users;
+}
+
+void add_user(User* user, User_list* users){
+    users->users[users->n_users] = user;
+    users->n_users++;
+}
+
+void free_users(User_list* users){
+    for (int i=0; i <users->n_users; i++){
+        free(users->users[i]->keywords);
+        free(users->users[i]);
+    }
+    free(users->users);
+    free(users);
+}
+
+bool is_players_ready(User_list* users){
+    for(int i=0; i < users->n_users; i++){
+        if (users->users[i]->status != READY){
+            return false;
+        }
+    }
+    return true;
+}
\ No newline at end of file
diff --git a/user.h b/user.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a2d92c9e797d973f18582b1a4f0f647237a5c33
--- /dev/null
+++ b/user.h
@@ -0,0 +1,30 @@
+#include <stdbool.h>
+typedef enum
+{
+    READY,
+    WAIT
+} STATUS;
+
+
+typedef struct User {
+    char* name;
+    char** keywords;
+    int n_keywords;
+    STATUS status;
+    int n_capacity;
+}User;
+
+typedef struct User_list{
+    int n_users;
+    User **users;
+}User_list;
+
+User* new_user();
+
+User_list* initialise_player_list();
+
+void add_user(User* user, User_list* users);
+
+void free_users(User_list* users);
+
+bool is_players_ready(User_list* users);
\ No newline at end of file
diff --git a/user.o b/user.o
new file mode 100644
index 0000000000000000000000000000000000000000..96afe21927a303d79fb739e295414526e16770b1
Binary files /dev/null and b/user.o differ