From 35eb2d98ae22d8ee475b69ce86fd0ef7afc82971 Mon Sep 17 00:00:00 2001 From: Mads Hartmann Date: Mon, 22 Aug 2011 11:28:51 +0200 Subject: [PATCH] Added a global chat in the lobby --- resources/board.xmlt | 3 +- resources/style.css | 251 +++++++++++++++++++++++++------------------ sass/style.scss | 202 +++++++++++++++++----------------- src/main.opa | 143 ++++++++++++++---------- src/types.opa | 4 + src/user.opa | 4 + 6 files changed, 347 insertions(+), 260 deletions(-) diff --git a/resources/board.xmlt b/resources/board.xmlt index f7d7b1e..d51bf06 100644 --- a/resources/board.xmlt +++ b/resources/board.xmlt @@ -89,4 +89,5 @@ - \ No newline at end of file + +

\ No newline at end of file diff --git a/resources/style.css b/resources/style.css index 2398806..ce6dc71 100644 --- a/resources/style.css +++ b/resources/style.css @@ -67,13 +67,12 @@ footer, header, hgroup, menu, nav, section { /* Form element styling */ -/* line 22, ../sass/style.scss */ +/* line 34, ../sass/style.scss */ input, textarea { padding: 9px; border: solid 1px #E5E5E5; outline: 0; font: normal 13px/100% Verdana, Tahoma, sans-serif; - width: 200px; color: #999; background: white url("bg_form.png") left top repeat-x; background: -webkit-gradient(linear, left top, left 25, from(white), color-stop(4%, #eeeeee), to(white)); @@ -82,8 +81,9 @@ input, textarea { -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1); -o-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1); box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1); + width: 200px; } -/* line 34, ../sass/style.scss */ +/* line 38, ../sass/style.scss */ input:hover, input:focus, textarea:hover, textarea:focus { border-color: #617798; -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.15); @@ -91,12 +91,12 @@ input:hover, input:focus, textarea:hover, textarea:focus { -o-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.15); box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.15); } -/* line 39, ../sass/style.scss */ +/* line 43, ../sass/style.scss */ input:focus, textarea:focus { color: #617798; } -/* line 44, ../sass/style.scss */ +/* line 48, ../sass/style.scss */ textarea { width: 400px; max-width: 400px; @@ -105,22 +105,142 @@ textarea { } /* - Other + General Structure of things. */ -/* line 55, ../sass/style.scss */ +/* line 59, ../sass/style.scss */ body { margin: 0px; background: url("/resources/bg.jpg") repeat scroll 0% 0%; } -/* line 60, ../sass/style.scss */ +/* line 64, ../sass/style.scss */ +.container { + width: 60%; + left: 20%; + margin: 0px; + top: 100px; + position: absolute; +} +/* line 71, ../sass/style.scss */ +.container .content { + overflow: hidden; + *zoom: 1; + background: #e0e0e0; + border-radius: 10px; + padding: 20px; + box-shadow: 0px 0px 5px black; +} +/* line 79, ../sass/style.scss */ +.container ul { + text-align: left; +} +/* line 83, ../sass/style.scss */ +.container input[type=submit] { + float: right; + margin-top: 20px; +} +/* line 88, ../sass/style.scss */ +.container#login { + width: 262px; + left: 50%; + margin-left: -131px; +} +/* line 95, ../sass/style.scss */ +.container#lobby input[type=submit] { + float: none; + margin-top: 0px; + width: 260px; +} +/* line 104, ../sass/style.scss */ +.container#create .button { + margin-left: 10px; +} +/* line 108, ../sass/style.scss */ +.container#create label { + width: 100px; + display: inline-block; +} +/* line 113, ../sass/style.scss */ +.container#create input { + width: 300px; +} +/* line 121, ../sass/style.scss */ +.container#lobby #main ul#menu { + margin: 0; + padding: 0; + border: 0; + overflow: hidden; + *zoom: 1; +} +/* line 60, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.11.3/frameworks/compass/stylesheets/compass/typography/lists/_horizontal-list.scss */ +.container#lobby #main ul#menu li { + list-style-image: none; + list-style-type: none; + margin-left: 0px; + white-space: nowrap; + display: inline; + float: left; + padding-left: 4px; + padding-right: 4px; +} +/* line 48, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.11.3/frameworks/compass/stylesheets/compass/typography/lists/_horizontal-list.scss */ +.container#lobby #main ul#menu li:first-child, .container#lobby #main ul#menu li.first { + padding-left: 0; +} +/* line 49, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.11.3/frameworks/compass/stylesheets/compass/typography/lists/_horizontal-list.scss */ +.container#lobby #main ul#menu li:last-child { + padding-right: 0; +} +/* line 50, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.11.3/frameworks/compass/stylesheets/compass/typography/lists/_horizontal-list.scss */ +.container#lobby #main ul#menu li.last { + padding-right: 0; +} +/* line 124, ../sass/style.scss */ +.container#lobby #main ul#menu li { + margin: 10px 0px; + text-align: center; +} +/* line 128, ../sass/style.scss */ +.container#lobby #main ul#menu li .button { + width: 199px; +} +/* line 135, ../sass/style.scss */ +.container#lobby .back { + display: inline-block; + margin: 0px 0px 10px 0px; + color: #000; + text-decoration: none; +} +/* line 143, ../sass/style.scss */ +.container #chat_messages { + padding: 9px; + border: solid 1px #E5E5E5; + outline: 0; + font: normal 13px/100% Verdana, Tahoma, sans-serif; + color: #999; + background: white url("bg_form.png") left top repeat-x; + background: -webkit-gradient(linear, left top, left 25, from(white), color-stop(4%, #eeeeee), to(white)); + background: -moz-linear-gradient(top, white, #eeeeee 1px, white 25px); + -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1); + -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1); + -o-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1); + box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1); + clear: both; + margin-bottom: 10px; +} +/* line 148, ../sass/style.scss */ +.container #chat_messages .user { + font-weight: bold; +} + +/* line 154, ../sass/style.scss */ #status { height: 45px; padding-bottom: 30px; text-align: center; color: #fff; } -/* line 66, ../sass/style.scss */ +/* line 160, ../sass/style.scss */ #status ul { margin: 0; padding: 0; @@ -157,17 +277,17 @@ body { #status ul li.last { padding-right: 0; } -/* line 75, ../sass/style.scss */ +/* line 169, ../sass/style.scss */ #status ul li { margin-left: 50px; float: right; } -/* line 80, ../sass/style.scss */ +/* line 174, ../sass/style.scss */ #status ul span { color: #fff; } -/* line 86, ../sass/style.scss */ +/* line 180, ../sass/style.scss */ #board { width: 750px; height: 750px; @@ -178,94 +298,37 @@ body { margin-top: -375px; margin-left: -375px; } -/* line 96, ../sass/style.scss */ +/* line 190, ../sass/style.scss */ #board table { margin-left: 75px; } -/* line 101, ../sass/style.scss */ +/* line 195, ../sass/style.scss */ td, th { text-align: center; width: 75px; height: 75px; } -/* line 107, ../sass/style.scss */ +/* line 201, ../sass/style.scss */ .selected { background: green; } -/* line 111, ../sass/style.scss */ +/* line 205, ../sass/style.scss */ .movable { background: orange; } -/* - login page -*/ -/* line 120, ../sass/style.scss */ -#signup, #login, #lobby { - width: 400px; - position: absolute; - left: 50%; - margin-left: -200px; - top: 100px; - color: #000; -} -/* line 129, ../sass/style.scss */ -#signup .content, #login .content, #lobby .content { - background: #e0e0e0; - border-radius: 10px; - padding: 20px; - box-shadow: 0px 0px 5px black; - overflow: hidden; - *zoom: 1; -} -/* line 137, ../sass/style.scss */ -#signup ul, #login ul, #lobby ul { - text-align: left; -} -/* line 141, ../sass/style.scss */ -#signup input[type=submit], #login input[type=submit], #lobby input[type=submit] { - float: right; - margin-top: 20px; -} - -/* line 147, ../sass/style.scss */ -#login { - width: 260px; - margin-left: -130px; -} - -/* line 153, ../sass/style.scss */ -#lobby input[type=submit] { - float: none; - margin-top: 0px; - width: 260px; -} - -/* line 160, ../sass/style.scss */ +/* line 210, ../sass/style.scss */ .hidden { display: none; } -/* - create page -*/ -/* line 170, ../sass/style.scss */ -#create label { - width: 100px; - display: inline-block; -} -/* line 175, ../sass/style.scss */ -#create input { - width: 300px; -} - /* forms */ -/* line 185, ../sass/style.scss */ +/* line 218, ../sass/style.scss */ .error_container { background: #b30a0a; margin: 20px 0px; @@ -273,24 +336,24 @@ td, th { border: 2px solid black; color: white; } -/* line 192, ../sass/style.scss */ +/* line 225, ../sass/style.scss */ .error_container ul { text-align: left; padding-left: 20px; list-style: disc; } -/* line 199, ../sass/style.scss */ +/* line 232, ../sass/style.scss */ .no_errors { display: none; } -/* line 203, ../sass/style.scss */ +/* line 236, ../sass/style.scss */ .has_errors { display: block; } -/* line 207, ../sass/style.scss */ +/* line 240, ../sass/style.scss */ .button, input[type=submit] { width: auto; padding: 9px 15px; @@ -306,16 +369,16 @@ td, th { -khtml-border-radius: 5px; border-radius: 5px; } -/* line 217, ../sass/style.scss */ +/* line 250, ../sass/style.scss */ .button:hover, input[type=submit]:hover { background: #617794; } -/* line 221, ../sass/style.scss */ +/* line 254, ../sass/style.scss */ .button:active, input[type=submit]:active { background: #6177CD; } -/* line 226, ../sass/style.scss */ +/* line 259, ../sass/style.scss */ .button { display: inline-block; } @@ -323,7 +386,7 @@ td, th { /* Board styling */ -/* line 232, ../sass/style.scss */ +/* line 265, ../sass/style.scss */ #waiting { position: absolute; width: 100%; @@ -332,7 +395,7 @@ td, th { left: 0px; background: rgba(0, 0, 0, 0.5); } -/* line 240, ../sass/style.scss */ +/* line 273, ../sass/style.scss */ #waiting h1 { text-align: center; color: #fff; @@ -345,23 +408,3 @@ td, th { margin-top: -100px; margin-left: -200px; } - -/* - Lobby styling -*/ -/* line 260, ../sass/style.scss */ -#lobby #menu li { - margin: 10px 0px; - text-align: center; -} -/* line 263, ../sass/style.scss */ -#lobby #menu li .button { - width: 200px; -} -/* line 269, ../sass/style.scss */ -#lobby .back { - display: inline-block; - margin: 0px 0px 10px 0px; - color: #000; - text-decoration: none; -} diff --git a/sass/style.scss b/sass/style.scss index 7a191dd..bca6eeb 100644 --- a/sass/style.scss +++ b/sass/style.scss @@ -15,25 +15,29 @@ $red: #B30A0A; $brick_dimensions: 75px; -/* - Form element styling -*/ - -input, textarea { - padding: 9px; +@mixin boxy() { + padding: 9px; border: solid 1px #E5E5E5; outline: 0; font: normal 13px/100% Verdana, Tahoma, sans-serif; - width: 200px; color: #999; background: #FFFFFF url('bg_form.png') left top repeat-x; background: -webkit-gradient(linear, left top, left 25, from(#FFFFFF), color-stop(4%, #EEEEEE), to(#FFFFFF)); background: -moz-linear-gradient(top, #FFFFFF, #EEEEEE 1px, #FFFFFF 25px); @include box-shadow(rgba(0, 0, 0, 0.1),0px, 0px, 8px); +} + +/* + Form element styling +*/ + +input, textarea { + @include boxy(); + width: 200px; &:hover, &:focus { - border-color: #617798; - @include box-shadow(rgba(0, 0, 0, 0.15),0px, 0px, 8px); + border-color: #617798; + @include box-shadow(rgba(0, 0, 0, 0.15),0px, 0px, 8px); }; &:focus { @@ -49,7 +53,7 @@ textarea { } /* - Other + General Structure of things. */ body { @@ -57,6 +61,96 @@ body { background : url("/resources/bg.jpg") repeat scroll 0% 0%; } +.container { + width : 60%; + left : 20%; + margin : 0px; + top : 100px; + position:absolute; + + .content { + @include clearfix; + background : rgba(224, 224, 224, 1); + border-radius: 10px; + padding : 20px; + box-shadow : 0px 0px 5px black; + } + + ul { + text-align: left; + } + + input[type=submit] { + float : right; + margin-top: 20px; + } + + &#login { + width : 262px; + left : 50%; + margin-left: -131px; + } + + &#lobby { + input[type=submit] { + float : none; + margin-top: 0px; + width : 260px; + } + } + + &#create { + + .button { + margin-left: 10px; + } + + label { + width : 100px; + display: inline-block; + } + + input { + width: 300px; + } + } + + &#lobby { + #main { + + ul#menu { + @include horizontal-list(); + + li { + margin : 10px 0px; + text-align: center; + + .button { + width: 199px; + } + } + } + } + + .back { + display : inline-block; + margin : 0px 0px 10px 0px; + color : #000; + text-decoration: none; + } + } + + #chat_messages { + @include boxy(); + clear : both; + margin-bottom: 10px; + + .user { + font-weight: bold; + } + } +} + #status { height: $brick_dimensions - 30px; padding-bottom: 30px; @@ -112,72 +206,11 @@ td, th { background: orange; } -/* - login page -*/ - - -#signup, #login, #lobby { - - width: 400px; - position: absolute; - left: 50%; - margin-left: -200px; - top: 100px; - color: #000; - - .content { - background: rgba(224, 224, 224, 1); - border-radius: 10px; - padding: 20px; - box-shadow: 0px 0px 5px black; - @include clearfix; - } - - ul { - text-align: left; - } - - input[type=submit] { - float: right; - margin-top: 20px; - } -} - -#login { - width: 260px; - margin-left: -130px; -} - -#lobby { - input[type=submit] { - float: none; - margin-top: 0px; - width: 260px; - } -} .hidden { display: none; } -/* - create page -*/ - -#create { - - label { - width: 100px; - display: inline-block; - } - - input { - width: 300px; - } - -} - /* forms */ @@ -249,29 +282,4 @@ td, th { margin-top: -100px; margin-left: -200px; } -} - -/* - Lobby styling -*/ - -#lobby { - #menu { - li { - margin: 10px 0px; - text-align: center; - .button { - width: 200px; - } - } - } - - .back { - display: inline-block; - margin: 0px 0px 10px 0px; - color: #000; - text-decoration: none; - } - -} - +} \ No newline at end of file diff --git a/src/main.opa b/src/main.opa index 0455509..111502b 100644 --- a/src/main.opa +++ b/src/main.opa @@ -23,7 +23,7 @@ show_error(xs: list(string)) = fourOfour() = Resource.styled_page("Chess", style,

404

-) +) login() = Resource.styled_page("Chess", style, @@ -37,7 +37,7 @@ login() = Resource.styled_page("Chess", style, Dom.give_focus(#username) -
+
    @@ -59,7 +59,7 @@ login() = Resource.styled_page("Chess", style, ) singup() = Resource.styled_page("Chess", style, -
    +
      @@ -92,53 +92,68 @@ singup() = Resource.styled_page("Chess", style,
      ) -lobby() = ( +/* + Chat +*/ + +type chat_message = { author : string ; text : string } + +@publish room = Network.cloud("room") : Network.network(chat_message) + +user_update(x : chat_message) = + line =
    • + {x.author}: + {x.text} +
    • + do Dom.transform([#chat_messages +<- line ]) + Dom.scroll_to_bottom(#chat_messages) + +broadcast(author) = + do Network.broadcast({~author text=Dom.get_value(#entry)}, room) + Dom.clear_value(#entry) +/* + End of Chat +*/ + +lobby() = User.withUser( user -> ( + + author = user.name + join_back_onclick() = - do Dom.remove_class(#menu, "hidden") + do Dom.remove_class(#main, "hidden") Dom.add_class(#join,"hidden") - + create_back_onclick() = - do Dom.remove_class(#menu, "hidden") + do Dom.remove_class(#main, "hidden") Dom.add_class(#create,"hidden") create_game_onclick() = - match User.get_status() with - | ~{user} -> ( - name = Dom.get_value(#name) - match Game.create(name, user) with - | {success = game } -> Client.goto("/game/" ^ name) - | {failure = xs } -> show_error(xs) - ) - | {unlogged} -> Client.goto("/login") - + name = Dom.get_value(#name) + match Game.create(name, user) with + | {success = game } -> Client.goto("/game/" ^ name) + | {failure = xs } -> show_error(xs) menu_create_a_game_onclick() = - match User.get_status() with - | { user = usr } -> - do Dom.remove_class(#create, "hidden") - Dom.add_class(#menu, "hidden") - | { unlogged } -> Client.goto("/login") - + do Dom.remove_class(#create, "hidden") + Dom.add_class(#main, "hidden") + menu_join_a_game_onclick() = - match User.get_status() with - | { user = usr } -> - do Dom.remove_class(#join,"hidden") - do Dom.add_class(#menu,"hidden") - do Dom.remove_content(#gamesList) - Map.To.val_list(/game) - |> List.filter_map( x -> x, _) - |> List.iter( x -> Dom.transform([#gamesList +<- -
    • - match Game.join(x.name, usr) with - | { success = game } -> Client.goto("/game/" ^ x.name) - | { failure = xs } -> show_error(xs) - }>{x.name}
    • ]), - _) - | {unlogged} -> Client.goto("/login") - + do Dom.remove_class(#join,"hidden") + do Dom.add_class(#main,"hidden") + do Dom.remove_content(#gamesList) + Map.To.val_list(/game) + |> List.filter_map( x -> x, _) + |> List.iter( x -> Dom.transform([#gamesList +<- +
    • + match Game.join(x.name, user) with + | { success = game } -> Client.goto("/game/" ^ x.name) + | { failure = xs } -> show_error(xs) + }>{x.name}
    • ]), + _) + Resource.styled_page("Chess", style, -
      +
        @@ -147,35 +162,42 @@ lobby() = ( - +
        + +
          Network.add_callback(user_update, room)}>
        + broadcast(author)} placeholder="Message..." /> +
        broadcast(author)}>Post +
        ) -) +), login()) /* Message received about the state of the game. */ @client message_recieved(msg: message) = match msg with - | { joining = user } -> Dom.remove(#waiting) - | { state = board } -> + | { joining = user } -> Dom.hide(#waiting) + | { state = board } -> do Board.update(board) - Dom.transform([#color_of_current_player <- colorc_to_string(board.current_color)]) + do Dom.transform([#color_of_current_player <- colorc_to_string(board.current_color)]) + if Option.get(Game.get_state()).color == board.current_color then + Dom.hide(#waiting) + else + do Dom.select_raw("#waiting h1") |> Dom.set_text(_, "Waiting for " ^ colorc_to_string(board.current_color)) + Dom.show(#waiting) @client when_ready(name,color): void = ( channel = Option.get(Game.get_state()).channel @@ -183,6 +205,14 @@ lobby() = ( do Dom.set_text(#name_of_game, name) do Dom.set_text(#color_of_current_player, colorc_to_string({white})) do Network.observe(message_recieved, channel) + + do Option.iter( state -> ( + if state.color == {white} then + Dom.select_raw("#waiting h1") |> Dom.set_text(_, "Waiting for black player") + else + Dom.select_raw("#waiting h1") |> Dom.set_text(_, "Waiting for white player") + ),Game.get_state()) + Board.prepare(Board.create()) ) @@ -197,14 +227,11 @@ boardgame(name: string) = (
        when_ready(name,color) }> {Template.parse(Template.default, @static_content("resources/board.xmlt")()) |> Template.to_xhtml(Template.default, _)}
        - - if (Option.get(game.white) == user) then ( - match game.black with - | ~{some} -> Resource.styled_page("Chess", style, xml({white})) - | {none} -> Resource.styled_page("Chess", style, <>{xml({white})}

        Waiting for another player to join

        ) - ) else ( + + if (Option.get(game.white) == user) then + Resource.styled_page("Chess", style, xml({white})) + else Resource.styled_page("Chess", style, xml({black})) - ) ) | {none} -> fourOfour() ) diff --git a/src/types.opa b/src/types.opa index 62d3cb0..3b8de92 100644 --- a/src/types.opa +++ b/src/types.opa @@ -37,6 +37,10 @@ colorc_to_string = | {white} -> "white" | {black} -> "black" +opposite_color = + | {white} -> {black} + | {black} -> {white} + kind_to_string = | {king} -> "king" | {queen} -> "queen" diff --git a/src/user.opa b/src/user.opa index b2d9bcb..9d33900 100644 --- a/src/user.opa +++ b/src/user.opa @@ -21,6 +21,10 @@ User = {{ state = UserContext.make({unlogged} : User.status) + withUser(f: user -> 'a, otherwise: 'a) = match get_status() with + | ~{user} -> f(user) + | {unlogged} -> otherwise + get_status() = UserContext.execute((a -> a), state)