<commit_before>module Shufflepuck exposing (create, default)

import Html exposing (Html)
import Math.Vector3 as V3 exposing (Vec3, vec3)
import Task exposing (Task)
import Time exposing (Time)
import Tuple exposing (first)
import WebGL.Texture as Texture exposing (Texture, Error)
import App exposing (App, AppMsg, Focus, appToFocus)
import Body exposing (..)
import Camera exposing (..)
import Camera.Util as Camera
import Control exposing (CtrlMsg)
import Dispatch exposing (..)
import Ground exposing (Ground)
import Model exposing (Inputs)
import Orientation exposing (Orientation)
import Body.Cube exposing (textureCube)
import Body.Sphere exposing (cloudsSphere, fogMountainsSphere)

import Bounding exposing (Bounding, bounce, bump)
import Bounding.Box exposing (Box, boundingBox)

type alias Attributes =
    { label : String
    , position : Vec3
    , scale : Vec3
    , orientation : Orientation
    , tableTexture : String
    , tableWidth : Float
    , tableLength : Float
    , tableThickness : Float
    , tableHeight : Float
    , puckRadius : Float
    , puckThickness : Float
    , puckHover : Float
    , paddleRadius : Float
    , paddleThickness : Float
    , paddleHover : Float
    }

default : Attributes
default =
    { label = "Shufflepuck"
    , position = vec3 0 0 0
    , scale = vec3 1 1 1
    , orientation = Orientation.initial
    , tableTexture = "resources/woodCrate.jpg"
    , tableWidth = 3
    , tableLength = 7
    , tableHeight = 3.0 -- 0.9
    , tableThickness = 0.2
    , puckRadius = 0.12
    , puckThickness = 0.03
    , puckHover = 0.2
    , paddleRadius = 0.18
    , paddleThickness = 0.07
    , paddleHover = 0.2
    }

type alias Model =
    { attributes : Attributes
    , table : Maybe Body
    , puck : Spherical (Moving Body)
    , paddle1 : Spherical (Moving Body)
    , paddle2 : Spherical (Moving Body)
    , bounds : Bounding Box
    }


type Msg
    = TextureLoaded (Result Error Texture)


create : Attributes -> ( App, Cmd AppMsg )
create attributes =
    App.create (init attributes)
        { label = always attributes.label
        , update = update
        , animate = animate
        , bodies = bodies
        , framing = framing
        , focus = focus
        , overlay = overlay
        }


-- | Move the entire table, maintaining the relative positions of the paddles and puck
reposition : Vec3 -> Model -> Model
reposition pos0 model =
    let
        a = model.attributes

        puckRelPos = V3.sub model.puck.position a.position
        paddle1RelPos = V3.sub model.paddle1.position a.position
        paddle2RelPos = V3.sub model.paddle2.position a.position

        bounds = model.bounds
        box = bounds.model
        boundsRelPos = V3.sub box.position a.position

        setPos pos body = { body | position = pos }
    in
        { model | attributes = { a | position = pos0 }
                , table = Maybe.map (setPos pos0) model.table
                , puck = setPos (V3.add pos0 puckRelPos) model.puck
                , paddle1 = setPos (V3.add pos0 paddle1RelPos) model.paddle1
                , paddle2 = setPos (V3.add pos0 paddle2RelPos) model.paddle2
                , bounds = { bounds | model = setPos (V3.add pos0 boundsRelPos) box }
        } 


init : Attributes -> ( Model, Cmd (CtrlMsg Msg) )
init a =
    let
        puckY = a.puckHover + (a.tableThickness + a.puckThickness) / 2.0
        paddleY = a.paddleHover + (a.tableThickness + a.paddleThickness) / 2.0
        paddleZ = a.tableLength / 4.0

        boundHeight = max (a.puckHover + a.puckThickness) (a.paddleThickness + a.paddleHover)
    in
        ( reposition a.position
            { attributes = { a | position = vec3 0 0 0 } -- First set up the table at 0 0 0, then reposition it
            , table = Nothing
            , puck =
                  { anchor = AnchorGround
                  , scale = vec3 a.puckRadius (a.puckThickness/2.0) a.puckRadius
                  , position = vec3 0 puckY 0
                  , orientation = Orientation.initial
                  , radius = a.puckRadius
                  , appear = cloudsSphere
                  , velocity = vec3 0.2 0 0.2
                  }
            , paddle1 =
                  { anchor = AnchorGround
                  , scale = vec3 a.paddleRadius (a.paddleThickness/2.0) a.paddleRadius
                  , position = vec3 0 paddleY -paddleZ
                  , orientation = Orientation.initial
                  , radius = a.paddleRadius
                  , appear = cloudsSphere
                  , velocity = vec3 0 0 0
                  }
            , paddle2 =
                  { anchor = AnchorGround
                  , scale = vec3 a.paddleRadius (a.paddleThickness/2.0) a.paddleRadius
                  , position = vec3 0 paddleY paddleZ
                  , orientation = Orientation.initial
                  , radius = a.paddleRadius
                  , appear = cloudsSphere
                  , velocity = vec3 0 0 0
                  }
            , bounds = boundingBox { position = vec3 (-a.tableWidth/2.0) 0 (-a.tableLength/2.0)
                                   , dimensions = vec3 a.tableWidth boundHeight a.tableLength
                                   }
            }
        , Texture.load a.tableTexture
            |> Task.attempt (Self << TextureLoaded)
        )


update :
    CtrlMsg Msg
    -> Model
    -> ( Model, Cmd (CtrlMsg Msg) )
update msg model =
    case msg of
        Self (TextureLoaded textureResult) ->
            case textureResult of
                Ok texture ->
                    let<commit_msg>shufflepuck: add mass to puck and paddles<commit_after>module Shufflepuck exposing (create, default)

import Html exposing (Html)
import Math.Vector3 as V3 exposing (Vec3, vec3)
import Task exposing (Task)
import Time exposing (Time)
import Tuple exposing (first)
import WebGL.Texture as Texture exposing (Texture, Error)
import App exposing (App, AppMsg, Focus, appToFocus)
import Body exposing (..)
import Camera exposing (..)
import Camera.Util as Camera
import Control exposing (CtrlMsg)
import Dispatch exposing (..)
import Ground exposing (Ground)
import Model exposing (Inputs)
import Orientation exposing (Orientation)
import Body.Cube exposing (textureCube)
import Body.Sphere exposing (cloudsSphere, fogMountainsSphere)

import Bounding exposing (Bounding, bounce, bump)
import Bounding.Box exposing (Box, boundingBox)

type alias Attributes =
    { label : String
    , position : Vec3
    , scale : Vec3
    , orientation : Orientation
    , tableTexture : String
    , tableWidth : Float
    , tableLength : Float
    , tableThickness : Float
    , tableHeight : Float
    , puckMass : Float
    , puckRadius : Float
    , puckThickness : Float
    , puckHover : Float
    , paddleMass : Float
    , paddleRadius : Float
    , paddleThickness : Float
    , paddleHover : Float
    }

default : Attributes
default =
    { label = "Shufflepuck"
    , position = vec3 0 0 0
    , scale = vec3 1 1 1
    , orientation = Orientation.initial
    , tableTexture = "resources/woodCrate.jpg"
    , tableWidth = 3
    , tableLength = 7
    , tableHeight = 3.0 -- 0.9
    , tableThickness = 0.2
    , puckMass = 0.1
    , puckRadius = 0.12
    , puckThickness = 0.03
    , puckHover = 0.2
    , paddleMass = 1.0
    , paddleRadius = 0.18
    , paddleThickness = 0.07
    , paddleHover = 0.2
    }

type alias Model =
    { attributes : Attributes
    , table : Maybe Body
    , puck : Massive (Spherical (Moving Body))
    , paddle1 : Massive (Spherical (Moving Body))
    , paddle2 : Massive (Spherical (Moving Body))
    , bounds : Bounding Box
    }


type Msg
    = TextureLoaded (Result Error Texture)


create : Attributes -> ( App, Cmd AppMsg )
create attributes =
    App.create (init attributes)
        { label = always attributes.label
        , update = update
        , animate = animate
        , bodies = bodies
        , framing = framing
        , focus = focus
        , overlay = overlay
        }


-- | Move the entire table, maintaining the relative positions of the paddles and puck
reposition : Vec3 -> Model -> Model
reposition pos0 model =
    let
        a = model.attributes

        puckRelPos = V3.sub model.puck.position a.position
        paddle1RelPos = V3.sub model.paddle1.position a.position
        paddle2RelPos = V3.sub model.paddle2.position a.position

        bounds = model.bounds
        box = bounds.model
        boundsRelPos = V3.sub box.position a.position

        setPos pos body = { body | position = pos }
    in
        { model | attributes = { a | position = pos0 }
                , table = Maybe.map (setPos pos0) model.table
                , puck = setPos (V3.add pos0 puckRelPos) model.puck
                , paddle1 = setPos (V3.add pos0 paddle1RelPos) model.paddle1
                , paddle2 = setPos (V3.add pos0 paddle2RelPos) model.paddle2
                , bounds = { bounds | model = setPos (V3.add pos0 boundsRelPos) box }
        } 


init : Attributes -> ( Model, Cmd (CtrlMsg Msg) )
init a =
    let
        puckY = a.puckHover + (a.tableThickness + a.puckThickness) / 2.0
        paddleY = a.paddleHover + (a.tableThickness + a.paddleThickness) / 2.0
        paddleZ = a.tableLength / 4.0

        boundHeight = max (a.puckHover + a.puckThickness) (a.paddleThickness + a.paddleHover)
    in
        ( reposition a.position
            { attributes = { a | position = vec3 0 0 0 } -- First set up the table at 0 0 0, then reposition it
            , table = Nothing
            , puck =
                  { anchor = AnchorGround
                  , scale = vec3 a.puckRadius (a.puckThickness/2.0) a.puckRadius
                  , position = vec3 0 puckY 0
                  , orientation = Orientation.initial
                  , radius = a.puckRadius
                  , mass = a.puckMass
                  , appear = cloudsSphere
                  , velocity = vec3 0.2 0 0.2
                  }
            , paddle1 =
                  { anchor = AnchorGround
                  , scale = vec3 a.paddleRadius (a.paddleThickness/2.0) a.paddleRadius
                  , position = vec3 0 paddleY -paddleZ
                  , orientation = Orientation.initial
                  , radius = a.paddleRadius
                  , mass = a.paddleMass
                  , appear = cloudsSphere
                  , velocity = vec3 0 0 0
                  }
            , paddle2 =
                  { anchor = AnchorGround
                  , scale = vec3 a.paddleRadius (a.paddleThickness/2.0) a.paddleRadius
                  , position = vec3 0 paddleY paddleZ
                  , orientation = Orientation.initial
                  , radius = a.paddleRadius
                  , mass = a.paddleMass
                  , appear = cloudsSphere
                  , velocity = vec3 0 0 0
                  }
            , bounds = boundingBox { position = vec3 (-a.tableWidth/2.0) 0 (-a.tableLength/2.0)
                                   , dimensions = vec3 a.tableWidth boundHeight a.tableLength
                                   }
            }
        , Texture.load a.tableTexture
            |> Task.attempt (Self << TextureLoaded)
        )


update :
    CtrlMsg Msg
    -> Model
    -> ( Model, Cmd (CtrlMsg Msg) )
update msg model =
    case msg of
        Self (TextureLoaded textureResult) ->
            case textureResult of
                Ok texture ->
                    let
{'fraction_non_alphanumeric': 0.08339160839160839, 'fraction_numerical': 0.02097902097902098, 'mean_word_length': 1.8062300711307333, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3683427', 'n_tokens_mistral': 3594, 'n_tokens_neox': 3226, 'n_words': 958}