Add tile rendering
Includes both black and white tile variants
6
priv/.gitignore
vendored
|
@ -1,2 +1,4 @@
|
|||
index.html
|
||||
elm-stuff
|
||||
riichi.js
|
||||
riichi.css
|
||||
elm-stuff/
|
||||
node_modules/
|
||||
|
|
|
@ -1,7 +1,37 @@
|
|||
all: index.html
|
||||
.PHONY: all node-deps clean run
|
||||
|
||||
index.html:
|
||||
elm-make --yes src/Riichi.elm --output=index.html --warn
|
||||
TARGET = js/riichi.js
|
||||
SOURCE = src/Riichi.elm
|
||||
CSS = css/riichi.css
|
||||
CSS_SOURCE = src/Stylesheets.elm
|
||||
|
||||
ELM_FILES = $(shell find . -type f -name '*.elm')
|
||||
PATH := ./node_modules/.bin:$(PATH)
|
||||
|
||||
ELMMAKE_FLAGS = --yes --warn
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
ELMMAKE_FLAGS += --debug
|
||||
endif
|
||||
|
||||
all: node-deps $(TARGET) $(CSS)
|
||||
|
||||
node-deps:
|
||||
npm i
|
||||
|
||||
$(TARGET): $(ELM_FILES)
|
||||
elm-make $(ELMMAKE_FLAGS) src/Riichi.elm --output=$@
|
||||
|
||||
$(CSS): $(CSS_SOURCE)
|
||||
elm-css $(CSS_SOURCE) -o css
|
||||
|
||||
clean-deps:
|
||||
rm -rf elm-stuff
|
||||
rm -rf node_modules
|
||||
|
||||
clean:
|
||||
rm -rf elm-stuff index.html
|
||||
rm -f $(TARGET) $(CSS)
|
||||
rm -rf elm-stuff/build-artifacts
|
||||
|
||||
run: all
|
||||
elm-reactor
|
||||
|
|
1
priv/css/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
riichi.css
|
|
@ -8,8 +8,12 @@
|
|||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"elm-community/list-extra": "6.1.0 <= v < 7.0.0",
|
||||
"elm-community/maybe-extra": "4.0.0 <= v < 5.0.0",
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0",
|
||||
"rtfeldman/elm-css": "9.1.0 <= v < 10.0.0",
|
||||
"rtfeldman/elm-css-helpers": "2.1.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
|
|
BIN
priv/images/Black/Back.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
priv/images/Black/Blank.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
priv/images/Black/Chun.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
priv/images/Black/Front.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
priv/images/Black/Haku.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
priv/images/Black/Hatsu.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
priv/images/Black/Man1.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
priv/images/Black/Man2.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
priv/images/Black/Man3.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
priv/images/Black/Man4.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
priv/images/Black/Man5-Dora.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
priv/images/Black/Man5.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
priv/images/Black/Man6.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
priv/images/Black/Man7.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
priv/images/Black/Man8.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
priv/images/Black/Man9.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
priv/images/Black/Nan.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
priv/images/Black/Pei.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
priv/images/Black/Pin1.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
priv/images/Black/Pin2.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
priv/images/Black/Pin3.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
priv/images/Black/Pin4.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
priv/images/Black/Pin5-Dora.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
priv/images/Black/Pin5.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
priv/images/Black/Pin6.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
priv/images/Black/Pin7.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
priv/images/Black/Pin8.png
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
priv/images/Black/Pin9.png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
priv/images/Black/Shaa.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
priv/images/Black/Sou1.png
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
priv/images/Black/Sou2.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
priv/images/Black/Sou3.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
priv/images/Black/Sou4.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
priv/images/Black/Sou5-Dora.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
priv/images/Black/Sou5.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
priv/images/Black/Sou6.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
priv/images/Black/Sou7.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
priv/images/Black/Sou8.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
priv/images/Black/Sou9.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
priv/images/Black/Ton.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
priv/images/White/Back.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
priv/images/White/Blank.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
priv/images/White/Chun.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
priv/images/White/Front.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
priv/images/White/Haku.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
priv/images/White/Hatsu.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
priv/images/White/Man1.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
priv/images/White/Man2.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
priv/images/White/Man3.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
priv/images/White/Man4.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
priv/images/White/Man5-Dora.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
priv/images/White/Man5.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
priv/images/White/Man6.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
priv/images/White/Man7.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
priv/images/White/Man8.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
priv/images/White/Man9.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
priv/images/White/Nan.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
priv/images/White/Pei.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
priv/images/White/Pin1.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
priv/images/White/Pin2.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
priv/images/White/Pin3.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
priv/images/White/Pin4.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
priv/images/White/Pin5-Dora.png
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
priv/images/White/Pin5.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
priv/images/White/Pin6.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
priv/images/White/Pin7.png
Normal file
After Width: | Height: | Size: 97 KiB |
BIN
priv/images/White/Pin8.png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
priv/images/White/Pin9.png
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
priv/images/White/Shaa.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
priv/images/White/Sou1.png
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
priv/images/White/Sou2.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
priv/images/White/Sou3.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
priv/images/White/Sou4.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
priv/images/White/Sou5-Dora.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
priv/images/White/Sou5.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
priv/images/White/Sou6.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
priv/images/White/Sou7.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
priv/images/White/Sou8.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
priv/images/White/Sou9.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
priv/images/White/Ton.png
Normal file
After Width: | Height: | Size: 35 KiB |
12
priv/index.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Riichi</title>
|
||||
<script type="text/javascript" src="/js/riichi.js"></script>
|
||||
<link rel="stylesheet" href="/css/riichi.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">Elm.Riichi.fullscreen()</script>
|
||||
</body>
|
||||
</html>
|
1
priv/js/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
riichi.js
|
8
priv/package.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "riichi",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"elm": "0.18",
|
||||
"elm-css": "0.6.1"
|
||||
}
|
||||
}
|
33
priv/src/Hand.elm
Normal file
|
@ -0,0 +1,33 @@
|
|||
module Hand exposing (..)
|
||||
|
||||
import Html exposing (Html, div, text)
|
||||
import Html.Attributes exposing (class)
|
||||
import Maybe.Extra
|
||||
import Tile exposing (Tile)
|
||||
|
||||
|
||||
type alias JSON =
|
||||
{ tiles : List String
|
||||
}
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ tiles : List Tile
|
||||
}
|
||||
|
||||
|
||||
fromJSON : JSON -> Model
|
||||
fromJSON j =
|
||||
{ tiles =
|
||||
j.tiles
|
||||
|> List.map Tile.fromString
|
||||
|> Maybe.Extra.values
|
||||
}
|
||||
|
||||
|
||||
view : Model -> Html a
|
||||
view model =
|
||||
div [ class "hand" ]
|
||||
[ div [ class "tiles open" ] <|
|
||||
List.map Tile.view model.tiles
|
||||
]
|
|
@ -1,10 +1,17 @@
|
|||
module Riichi exposing (..)
|
||||
|
||||
import Hand
|
||||
import Html exposing (..)
|
||||
import Html.CssHelpers
|
||||
import Stylesheets as S
|
||||
|
||||
|
||||
{ id, class, classList } =
|
||||
Html.CssHelpers.withNamespace "riichi"
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
{ hand : Hand.Model }
|
||||
|
||||
|
||||
type Msg
|
||||
|
@ -13,7 +20,24 @@ type Msg
|
|||
|
||||
init : ( Model, Cmd Msg )
|
||||
init =
|
||||
( {}, Cmd.none )
|
||||
( { hand =
|
||||
Hand.fromJSON
|
||||
{ tiles =
|
||||
[ "4 pin"
|
||||
, "5 pin"
|
||||
, "6 pin"
|
||||
, "4 sou"
|
||||
, "5 sou"
|
||||
, "6 sou"
|
||||
, "4 man"
|
||||
, "5 man"
|
||||
, "6 man"
|
||||
, "red dragon"
|
||||
]
|
||||
}
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||
|
@ -33,5 +57,7 @@ main =
|
|||
|
||||
view : Model -> Html Msg
|
||||
view model =
|
||||
div []
|
||||
[ h1 [] [ text "Riichi Mahjong" ] ]
|
||||
div [ class [ S.Tileset S.White ] ]
|
||||
[ h1 [] [ text "Riichi Mahjong" ]
|
||||
, Hand.view model.hand
|
||||
]
|
||||
|
|
105
priv/src/Stylesheets.elm
Normal file
|
@ -0,0 +1,105 @@
|
|||
port module Stylesheets exposing (..)
|
||||
|
||||
import Css exposing (..)
|
||||
import Css.Elements exposing (..)
|
||||
import Css.Namespace exposing (namespace)
|
||||
import Css.File exposing (CssFileStructure, CssCompilerProgram)
|
||||
|
||||
|
||||
type Tileset
|
||||
= White
|
||||
| Black
|
||||
|
||||
|
||||
type Class
|
||||
= Tile String
|
||||
| Tileset Tileset
|
||||
|
||||
|
||||
riichi : Stylesheet
|
||||
riichi =
|
||||
(stylesheet << namespace "riichi") <|
|
||||
List.concat
|
||||
[ List.map tile tiles
|
||||
, List.map (tileset White) tiles
|
||||
, List.map (tileset Black) tiles
|
||||
]
|
||||
|
||||
|
||||
applyTileset : Tileset -> String -> Style
|
||||
applyTileset set tile =
|
||||
batch
|
||||
[ backgroundImage (tileImage set "Front")
|
||||
, children
|
||||
[ span
|
||||
[ backgroundImage (tileImage set tile) ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
tile : String -> Snippet
|
||||
tile tile =
|
||||
class (Tile tile)
|
||||
[ display inlineBlock
|
||||
, applyTileset White tile
|
||||
, margin (px 10)
|
||||
, width (px 60)
|
||||
, height (px 80)
|
||||
, backgroundSize (pct 100)
|
||||
, children
|
||||
[ span
|
||||
[ display block
|
||||
, height (pct 100)
|
||||
, width (pct 100)
|
||||
, backgroundSize (pct 80)
|
||||
, backgroundRepeat noRepeat
|
||||
, backgroundPosition center
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
tileset : Tileset -> String -> Snippet
|
||||
tileset set tile =
|
||||
class (Tileset set)
|
||||
[ descendants
|
||||
[ class (Tile tile)
|
||||
[ applyTileset set tile ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
tiles : List String
|
||||
tiles =
|
||||
List.concat
|
||||
[ [ "Chun"
|
||||
, "Hatsu"
|
||||
, "Haku"
|
||||
, "Ton"
|
||||
, "Nan"
|
||||
, "Shaa"
|
||||
, "Pei"
|
||||
]
|
||||
, List.range 1 9 |> List.map toString |> List.map (String.append "Pin")
|
||||
, List.range 1 9 |> List.map toString |> List.map (String.append "Sou")
|
||||
, List.range 1 9 |> List.map toString |> List.map (String.append "Man")
|
||||
]
|
||||
|
||||
|
||||
tileImage : Tileset -> String -> BackgroundImage {}
|
||||
tileImage set tile =
|
||||
url (String.concat [ "../images/", toString set, "/", tile, ".png" ])
|
||||
|
||||
|
||||
port files : CssFileStructure -> Cmd msg
|
||||
|
||||
|
||||
fileStructure : CssFileStructure
|
||||
fileStructure =
|
||||
Css.File.toFileStructure
|
||||
[ ( "riichi.css", Css.File.compile [ riichi ] ) ]
|
||||
|
||||
|
||||
main : CssCompilerProgram
|
||||
main =
|
||||
Css.File.compiler files fileStructure
|
159
priv/src/Tile.elm
Normal file
|
@ -0,0 +1,159 @@
|
|||
module Tile exposing (..)
|
||||
|
||||
import Dict
|
||||
import Html exposing (Html, span, text)
|
||||
import Html.CssHelpers
|
||||
import List.Extra
|
||||
import String
|
||||
import Stylesheets as S
|
||||
|
||||
|
||||
{ id, class, classList } =
|
||||
Html.CssHelpers.withNamespace "riichi"
|
||||
|
||||
|
||||
type Wind
|
||||
= East
|
||||
| South
|
||||
| West
|
||||
| North
|
||||
|
||||
|
||||
type Dragon
|
||||
= Green
|
||||
| Red
|
||||
| White
|
||||
|
||||
|
||||
type Suit
|
||||
= Pin
|
||||
| Sou
|
||||
| Man
|
||||
|
||||
|
||||
type Tile
|
||||
= Wind Wind
|
||||
| Dragon Dragon
|
||||
| Suited Suit Int
|
||||
|
||||
|
||||
type CssClass
|
||||
= Tile Tile
|
||||
|
||||
|
||||
fromString : String -> Maybe Tile
|
||||
fromString s =
|
||||
let
|
||||
parts =
|
||||
String.toLower s
|
||||
|> String.split " "
|
||||
in
|
||||
case parts of
|
||||
[ value, suit ] ->
|
||||
make suit value
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
||||
|
||||
make : String -> String -> Maybe Tile
|
||||
make suit value =
|
||||
let
|
||||
winds =
|
||||
Dict.fromList
|
||||
[ ( "east", East )
|
||||
, ( "south", South )
|
||||
, ( "west", West )
|
||||
, ( "north", North )
|
||||
]
|
||||
|
||||
dragons =
|
||||
Dict.fromList
|
||||
[ ( "green", Green )
|
||||
, ( "red", Red )
|
||||
, ( "white", White )
|
||||
]
|
||||
|
||||
suits =
|
||||
Dict.fromList
|
||||
[ ( "pin", Pin )
|
||||
, ( "sou", Sou )
|
||||
, ( "man", Man )
|
||||
]
|
||||
in
|
||||
case suit of
|
||||
"wind" ->
|
||||
Dict.get value winds
|
||||
|> Maybe.map Wind
|
||||
|
||||
"dragon" ->
|
||||
Dict.get value dragons
|
||||
|> Maybe.map Dragon
|
||||
|
||||
_ ->
|
||||
let
|
||||
s =
|
||||
Dict.get suit suits
|
||||
|
||||
v =
|
||||
String.toInt value
|
||||
|> Result.toMaybe
|
||||
|> Maybe.andThen
|
||||
(\x ->
|
||||
if (x >= 1) && (x <= 9) then
|
||||
Just x
|
||||
else
|
||||
Nothing
|
||||
)
|
||||
in
|
||||
Maybe.map2 Suited s v
|
||||
|
||||
|
||||
tiles : List Tile
|
||||
tiles =
|
||||
List.concat
|
||||
[ List.map Wind [ East, South, West, North ]
|
||||
, List.map Dragon [ Red, Green, White ]
|
||||
, List.Extra.lift2 Suited
|
||||
[ Man, Sou, Pin ]
|
||||
(List.range 1 9)
|
||||
]
|
||||
|
||||
|
||||
cssName : Tile -> String
|
||||
cssName tile =
|
||||
case tile of
|
||||
Dragon Red ->
|
||||
"Chun"
|
||||
|
||||
Dragon Green ->
|
||||
"Hatsu"
|
||||
|
||||
Dragon White ->
|
||||
"Haku"
|
||||
|
||||
Wind East ->
|
||||
"Ton"
|
||||
|
||||
Wind South ->
|
||||
"Nan"
|
||||
|
||||
Wind West ->
|
||||
"Shaa"
|
||||
|
||||
Wind North ->
|
||||
"Pei"
|
||||
|
||||
Suited Pin v ->
|
||||
String.concat [ "Pin", (toString v) ]
|
||||
|
||||
Suited Sou v ->
|
||||
String.concat [ "Sou", (toString v) ]
|
||||
|
||||
Suited Man v ->
|
||||
String.concat [ "Wan", (toString v) ]
|
||||
|
||||
|
||||
view : Tile -> Html a
|
||||
view tile =
|
||||
span [ class [ (S.Tile (cssName tile)) ] ] [ span [] [] ]
|
|
@ -11,7 +11,11 @@
|
|||
|
||||
start(_StartType, _StartArgs) ->
|
||||
Dispatch = cowboy_router:compile(
|
||||
[{'_', [{"/", cowboy_static, {priv_file, riichi, "index.html"}}]}
|
||||
[{'_', [{"/", cowboy_static, {priv_file, riichi, "index.html"}},
|
||||
{"/js/[...]", cowboy_static, {priv_dir, riichi, "js"}},
|
||||
{"/css/[...]", cowboy_static, {priv_dir, riichi, "css"}},
|
||||
{"/images/[...]", cowboy_static, {priv_dir, riichi, "images"}}
|
||||
]}
|
||||
]),
|
||||
{ok, _} = cowboy:start_http(
|
||||
my_http_listener,
|
||||
|
|