Rename more stuff
This commit is contained in:
1
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/.gitignore
vendored
Normal file
1
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
elm-stuff
|
||||
30
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/LICENSE
vendored
Normal file
30
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/LICENSE
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
Copyright (c) 2014, Max Goldstein
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of Max Goldstein nor the names of other
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
62
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/README.md
vendored
Normal file
62
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/README.md
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# Format String for Elm
|
||||
by Max Goldstein
|
||||
|
||||
Create format strings for dates in the Elm programming language.
|
||||
|
||||
## Documentation
|
||||
|
||||
The module `Date.Format` exports `format : String -> Date.Date -> String`.
|
||||
The `Date` refers to Elm's standard [Date library](http://package.elm-lang.org/packages/elm-lang/core/latest/Date).
|
||||
The input `String` may contain any of the following directives, which will be expanded to parts of the date.
|
||||
|
||||
A directive consists of a percent (%) character, zero or more flags and a conversion specifier as follows.
|
||||
|
||||
```
|
||||
%<flags><conversion>
|
||||
```
|
||||
|
||||
Flags:
|
||||
|
||||
* `-` - don't pad a numerical output
|
||||
* `_` - use spaces for padding
|
||||
* `0` - use zeros for padding
|
||||
|
||||
Format directives:
|
||||
|
||||
* `%Y` - 4 digit year
|
||||
* `%y` - 2 digit year
|
||||
* `%m` - Zero-padded month of year, e.g. `"07"` for July
|
||||
* `%B` - Full month name, e.g. `"July"`
|
||||
* `%b` - Abbreviated month name, e.g. `"Jul"`
|
||||
* `%d` - Zero-padded day of month, e.g `"02"`
|
||||
* `%e` - Space-padded day of month, e.g `" 2"`
|
||||
* `%a` - Day of week, abbreviated to three letters, e.g. `"Wed"`
|
||||
* `%A` - Day of week in full, e.g. `"Wednesday"`
|
||||
* `%H` - Hour of the day, 24-hour clock, zero-padded
|
||||
* `%k` - Hour of the day, 24-hour clock, space-padded
|
||||
* `%I` - Hour of the day, 12-hour clock, zero-padded
|
||||
* `%l` - (lower ell) Hour of the day, 12-hour clock, space-padded
|
||||
* `%p` - AM or PM
|
||||
* `%P` - am or pm
|
||||
* `%M` - Minute of the hour, zero-padded
|
||||
* `%S` - Second of the minute, zero-padded
|
||||
* `%L` - Millisecond of the second, zero-padded
|
||||
* `%%` - literal `%`
|
||||
|
||||
## Localization
|
||||
|
||||
`Date.Format` also exports `localFormat : Date.Local.Local -> String -> Date.Date -> String`.
|
||||
This function allows to add a localization record as specified in `Date.Local`.
|
||||
It can be used to display local terms for week days, months, and AM or PM.
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are welcome! Note that in addition to adding a new letter to the
|
||||
massive case statement, you'll also need to add it to the regex. Languages like
|
||||
[Haskell](http://www.haskell.org/ghc/docs/6.12.3/html/libraries/time-1.1.4/Data-Time-Format.html),
|
||||
[Python](https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior),
|
||||
and [Ruby](http://apidock.com/ruby/DateTime/strftime) have very comprehensive
|
||||
format strings. (Luckily, they seem to agree on the encoding, which you should
|
||||
follow.) I've tried to add the most common formats, but if you want one added,
|
||||
send a PR (and add a passing test). To run the tests, run `elm test` (which you
|
||||
can install from the [elm-test](https://github.com/elm-community/elm-test) package).
|
||||
18
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/elm-package.json
vendored
Normal file
18
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/elm-package.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": "1.4.2",
|
||||
"summary": "Format dates with ease",
|
||||
"repository": "https://github.com/mgold/elm-date-format.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": [
|
||||
"Date.Format",
|
||||
"Date.Local",
|
||||
"Time.Format"
|
||||
],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
274
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/src/Date/Format.elm
vendored
Normal file
274
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/src/Date/Format.elm
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
module Date.Format exposing (format, formatISO8601, localFormat)
|
||||
|
||||
{-| Format strings for dates.
|
||||
|
||||
@docs format, localFormat, formatISO8601
|
||||
|
||||
-}
|
||||
|
||||
import Date
|
||||
import Date.Local exposing (Local, international)
|
||||
import List exposing (head, tail)
|
||||
import Maybe exposing (andThen, withDefault)
|
||||
import Regex
|
||||
import String exposing (padLeft, right, toUpper)
|
||||
|
||||
|
||||
re : Regex.Regex
|
||||
re =
|
||||
Regex.regex "%(_|-|0)?(%|Y|y|m|B|b|d|e|a|A|H|k|I|l|L|p|P|M|S)"
|
||||
|
||||
|
||||
type Padding
|
||||
= NoPadding
|
||||
| Space
|
||||
| Zero
|
||||
| ZeroThreeDigits
|
||||
|
||||
|
||||
{-| Use a format string to format a date. See the
|
||||
[README](https://github.com/mgold/elm-date-format/blob/master/README.md) for a
|
||||
list of accepted formatters.
|
||||
-}
|
||||
format : String -> Date.Date -> String
|
||||
format s d =
|
||||
localFormat international s d
|
||||
|
||||
|
||||
{-| Use a localization record and a format string to format a date. See the
|
||||
[README](https://github.com/mgold/elm-date-format/blob/master/README.md) for a
|
||||
list of accepted formatters.
|
||||
-}
|
||||
localFormat : Local -> String -> Date.Date -> String
|
||||
localFormat loc s d =
|
||||
Regex.replace Regex.All re (formatToken loc d) s
|
||||
|
||||
|
||||
{-| Formats a UTC date acording to
|
||||
[ISO-8601](https://en.wikipedia.org/wiki/ISO_8601). This is commonly used to
|
||||
send dates to a server. For example: `2016-01-06T09:22:00Z`.
|
||||
-}
|
||||
formatISO8601 : Date.Date -> String
|
||||
formatISO8601 =
|
||||
format "%Y-%m-%dT%H:%M:%SZ"
|
||||
|
||||
|
||||
formatToken : Local -> Date.Date -> Regex.Match -> String
|
||||
formatToken loc d m =
|
||||
let
|
||||
( padding, symbol ) =
|
||||
case m.submatches of
|
||||
[ Just "-", Just x ] ->
|
||||
( Just NoPadding, x )
|
||||
|
||||
[ Just "_", Just x ] ->
|
||||
( Just Space, x )
|
||||
|
||||
[ Just "0", Just x ] ->
|
||||
( Just Zero, x )
|
||||
|
||||
[ Nothing, Just x ] ->
|
||||
( Nothing, x )
|
||||
|
||||
_ ->
|
||||
( Nothing, " " )
|
||||
in
|
||||
case symbol of
|
||||
"%" ->
|
||||
"%"
|
||||
|
||||
"Y" ->
|
||||
d |> Date.year |> toString
|
||||
|
||||
"y" ->
|
||||
d |> Date.year |> toString |> right 2
|
||||
|
||||
"m" ->
|
||||
d |> Date.month |> monthToInt |> padWith (withDefault Zero padding)
|
||||
|
||||
"B" ->
|
||||
d |> Date.month |> monthToWord loc.date.months
|
||||
|
||||
"b" ->
|
||||
d |> Date.month |> monthToWord loc.date.monthsAbbrev
|
||||
|
||||
"d" ->
|
||||
d |> Date.day |> padWith (withDefault Zero padding)
|
||||
|
||||
"e" ->
|
||||
d |> Date.day |> padWith (withDefault Space padding)
|
||||
|
||||
"a" ->
|
||||
d |> Date.dayOfWeek |> dayOfWeekToWord loc.date.wdaysAbbrev
|
||||
|
||||
"A" ->
|
||||
d |> Date.dayOfWeek |> dayOfWeekToWord loc.date.wdays
|
||||
|
||||
"H" ->
|
||||
d |> Date.hour |> padWith (withDefault Zero padding)
|
||||
|
||||
"k" ->
|
||||
d |> Date.hour |> padWith (withDefault Space padding)
|
||||
|
||||
"I" ->
|
||||
d |> Date.hour |> mod12 |> zero2twelve |> padWith (withDefault Zero padding)
|
||||
|
||||
"l" ->
|
||||
d |> Date.hour |> mod12 |> zero2twelve |> padWith (withDefault Space padding)
|
||||
|
||||
"p" ->
|
||||
if Date.hour d < 12 then
|
||||
toUpper loc.time.am
|
||||
else
|
||||
toUpper loc.time.pm
|
||||
|
||||
"P" ->
|
||||
if Date.hour d < 12 then
|
||||
loc.time.am
|
||||
else
|
||||
loc.time.pm
|
||||
|
||||
"M" ->
|
||||
d |> Date.minute |> padWith (withDefault Zero padding)
|
||||
|
||||
"S" ->
|
||||
d |> Date.second |> padWith (withDefault Zero padding)
|
||||
|
||||
"L" ->
|
||||
d |> Date.millisecond |> padWith (withDefault ZeroThreeDigits padding)
|
||||
|
||||
_ ->
|
||||
""
|
||||
|
||||
|
||||
monthToInt m =
|
||||
case m of
|
||||
Date.Jan ->
|
||||
1
|
||||
|
||||
Date.Feb ->
|
||||
2
|
||||
|
||||
Date.Mar ->
|
||||
3
|
||||
|
||||
Date.Apr ->
|
||||
4
|
||||
|
||||
Date.May ->
|
||||
5
|
||||
|
||||
Date.Jun ->
|
||||
6
|
||||
|
||||
Date.Jul ->
|
||||
7
|
||||
|
||||
Date.Aug ->
|
||||
8
|
||||
|
||||
Date.Sep ->
|
||||
9
|
||||
|
||||
Date.Oct ->
|
||||
10
|
||||
|
||||
Date.Nov ->
|
||||
11
|
||||
|
||||
Date.Dec ->
|
||||
12
|
||||
|
||||
|
||||
monthToWord loc m =
|
||||
case m of
|
||||
Date.Jan ->
|
||||
loc.jan
|
||||
|
||||
Date.Feb ->
|
||||
loc.feb
|
||||
|
||||
Date.Mar ->
|
||||
loc.mar
|
||||
|
||||
Date.Apr ->
|
||||
loc.apr
|
||||
|
||||
Date.May ->
|
||||
loc.may
|
||||
|
||||
Date.Jun ->
|
||||
loc.jun
|
||||
|
||||
Date.Jul ->
|
||||
loc.jul
|
||||
|
||||
Date.Aug ->
|
||||
loc.aug
|
||||
|
||||
Date.Sep ->
|
||||
loc.sep
|
||||
|
||||
Date.Oct ->
|
||||
loc.oct
|
||||
|
||||
Date.Nov ->
|
||||
loc.nov
|
||||
|
||||
Date.Dec ->
|
||||
loc.dec
|
||||
|
||||
|
||||
dayOfWeekToWord loc dow =
|
||||
case dow of
|
||||
Date.Mon ->
|
||||
loc.mon
|
||||
|
||||
Date.Tue ->
|
||||
loc.tue
|
||||
|
||||
Date.Wed ->
|
||||
loc.wed
|
||||
|
||||
Date.Thu ->
|
||||
loc.thu
|
||||
|
||||
Date.Fri ->
|
||||
loc.fri
|
||||
|
||||
Date.Sat ->
|
||||
loc.sat
|
||||
|
||||
Date.Sun ->
|
||||
loc.sun
|
||||
|
||||
|
||||
mod12 h =
|
||||
h % 12
|
||||
|
||||
|
||||
zero2twelve n =
|
||||
if n == 0 then
|
||||
12
|
||||
else
|
||||
n
|
||||
|
||||
|
||||
padWith : Padding -> a -> String
|
||||
padWith padding =
|
||||
let
|
||||
padder =
|
||||
case padding of
|
||||
NoPadding ->
|
||||
identity
|
||||
|
||||
Zero ->
|
||||
padLeft 2 '0'
|
||||
|
||||
ZeroThreeDigits ->
|
||||
padLeft 3 '0'
|
||||
|
||||
Space ->
|
||||
padLeft 2 ' '
|
||||
in
|
||||
padder << toString
|
||||
207
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/src/Date/Local.elm
vendored
Normal file
207
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/src/Date/Local.elm
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
module Date.Local exposing (Local, Months, WeekDays, TimeZones, international, french)
|
||||
|
||||
{-| A record type to store localized time formatting information.
|
||||
|
||||
@docs international, french
|
||||
|
||||
@docs Local, Months, WeekDays, TimeZones
|
||||
|
||||
-}
|
||||
|
||||
import Dict exposing (Dict)
|
||||
|
||||
|
||||
{-| A collection of strings and formats for localizing formats.
|
||||
|
||||
Time zones and default formats are not implemented,
|
||||
but included to avoid possible version conflicts in the future.
|
||||
-}
|
||||
type alias Local =
|
||||
{ date :
|
||||
{ months : Months
|
||||
, monthsAbbrev : Months
|
||||
, wdays : WeekDays
|
||||
, wdaysAbbrev : WeekDays
|
||||
, defaultFormat :
|
||||
Maybe String
|
||||
-- for %x
|
||||
}
|
||||
, time :
|
||||
{ am : String
|
||||
, pm : String
|
||||
, defaultFormat :
|
||||
Maybe String
|
||||
-- for %X
|
||||
}
|
||||
, timeZones :
|
||||
Maybe TimeZones
|
||||
-- for %Z
|
||||
, defaultFormat :
|
||||
Maybe String
|
||||
-- for %c
|
||||
}
|
||||
|
||||
|
||||
{-| A record of names for the months of the year.
|
||||
-}
|
||||
type alias Months =
|
||||
{ jan : String
|
||||
, feb : String
|
||||
, mar : String
|
||||
, apr : String
|
||||
, may : String
|
||||
, jun : String
|
||||
, jul : String
|
||||
, aug : String
|
||||
, sep : String
|
||||
, oct : String
|
||||
, nov : String
|
||||
, dec : String
|
||||
}
|
||||
|
||||
|
||||
{-| A record of names for the days of the week.
|
||||
-}
|
||||
type alias WeekDays =
|
||||
{ mon : String
|
||||
, tue : String
|
||||
, wed : String
|
||||
, thu : String
|
||||
, fri : String
|
||||
, sat : String
|
||||
, sun : String
|
||||
}
|
||||
|
||||
|
||||
{-| Maps from %z type string (+hhmm or -hhmm) to timezone name or abbreviation.
|
||||
|
||||
Not currently implemented.
|
||||
-}
|
||||
type alias TimeZones =
|
||||
Dict String String
|
||||
|
||||
|
||||
{-| A default set of localizations.
|
||||
-}
|
||||
international : Local
|
||||
international =
|
||||
{ date =
|
||||
{ months =
|
||||
{ jan = "January"
|
||||
, feb = "February"
|
||||
, mar = "March"
|
||||
, apr = "April"
|
||||
, may = "May"
|
||||
, jun = "June"
|
||||
, jul = "July"
|
||||
, aug = "August"
|
||||
, sep = "September"
|
||||
, oct = "October"
|
||||
, nov = "November"
|
||||
, dec = "December"
|
||||
}
|
||||
, monthsAbbrev =
|
||||
{ jan = "Jan"
|
||||
, feb = "Feb"
|
||||
, mar = "Mar"
|
||||
, apr = "Apr"
|
||||
, may = "May"
|
||||
, jun = "Jun"
|
||||
, jul = "Jul"
|
||||
, aug = "Aug"
|
||||
, sep = "Sep"
|
||||
, oct = "Oct"
|
||||
, nov = "Nov"
|
||||
, dec = "Dec"
|
||||
}
|
||||
, wdays =
|
||||
{ mon = "Monday"
|
||||
, tue = "Tuesday"
|
||||
, wed = "Wednesday"
|
||||
, thu = "Thursday"
|
||||
, fri = "Friday"
|
||||
, sat = "Saturday"
|
||||
, sun = "Sunday"
|
||||
}
|
||||
, wdaysAbbrev =
|
||||
{ mon = "Mon"
|
||||
, tue = "Tue"
|
||||
, wed = "Wed"
|
||||
, thu = "Thu"
|
||||
, fri = "Fri"
|
||||
, sat = "Sat"
|
||||
, sun = "Sun"
|
||||
}
|
||||
, defaultFormat = Nothing
|
||||
}
|
||||
, time =
|
||||
{ am = "am"
|
||||
, pm = "pm"
|
||||
, defaultFormat = Nothing
|
||||
}
|
||||
, timeZones = Nothing
|
||||
, defaultFormat = Nothing
|
||||
}
|
||||
|
||||
|
||||
{-| French set of localizations.
|
||||
-}
|
||||
french : Local
|
||||
french =
|
||||
{ date =
|
||||
{ months =
|
||||
{ jan = "Janvier"
|
||||
, feb = "Février"
|
||||
, mar = "Mars"
|
||||
, apr = "Avril"
|
||||
, may = "Mai"
|
||||
, jun = "Juin"
|
||||
, jul = "Juillet"
|
||||
, aug = "Août"
|
||||
, sep = "Septembre"
|
||||
, oct = "Octobre"
|
||||
, nov = "Novembre"
|
||||
, dec = "Décembre"
|
||||
}
|
||||
, monthsAbbrev =
|
||||
{ jan = "Jan"
|
||||
, feb = "Fév"
|
||||
, mar = "Mar"
|
||||
, apr = "Avr"
|
||||
, may = "Mai"
|
||||
, jun = "Jui"
|
||||
, jul = "Jul"
|
||||
, aug = "Aoû"
|
||||
, sep = "Sep"
|
||||
, oct = "Oct"
|
||||
, nov = "Nov"
|
||||
, dec = "Déc"
|
||||
}
|
||||
, wdays =
|
||||
{ mon = "Lundi"
|
||||
, tue = "Mardi"
|
||||
, wed = "Mercredi"
|
||||
, thu = "Jeudi"
|
||||
, fri = "Vendredi"
|
||||
, sat = "Samedi"
|
||||
, sun = "Dimanche"
|
||||
}
|
||||
, wdaysAbbrev =
|
||||
{ mon = "Lun"
|
||||
, tue = "Mar"
|
||||
, wed = "Mer"
|
||||
, thu = "Jeu"
|
||||
, fri = "Ven"
|
||||
, sat = "Sam"
|
||||
, sun = "Dim"
|
||||
}
|
||||
, defaultFormat = Nothing
|
||||
}
|
||||
, time =
|
||||
{ am = "am"
|
||||
, pm = "pm"
|
||||
, defaultFormat = Nothing
|
||||
}
|
||||
, timeZones = Nothing
|
||||
, defaultFormat = Nothing
|
||||
}
|
||||
19
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/src/Time/Format.elm
vendored
Normal file
19
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/src/Time/Format.elm
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
module Time.Format exposing (format)
|
||||
|
||||
{-| Format strings for times.
|
||||
|
||||
@docs format
|
||||
-}
|
||||
|
||||
import Time
|
||||
import Date.Format
|
||||
import Date
|
||||
|
||||
|
||||
{-| Use a format string to format a time. See the
|
||||
[README](https://github.com/mgold/elm-date-format/blob/master/README.md) for a
|
||||
list of accepted formatters.
|
||||
-}
|
||||
format : String -> Time.Time -> String
|
||||
format s t =
|
||||
Date.Format.format s (Date.fromTime t)
|
||||
146
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/tests/Tests.elm
vendored
Normal file
146
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/tests/Tests.elm
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
module Tests exposing (all)
|
||||
|
||||
{- A simple test an example of the library.
|
||||
Does not test every option, you can submit PRs for that.
|
||||
-}
|
||||
|
||||
import Date
|
||||
import Date.Format
|
||||
import Expect
|
||||
import String exposing (join, padLeft)
|
||||
import Test exposing (..)
|
||||
import Time
|
||||
import Time.Format
|
||||
|
||||
|
||||
-- test name, expected value, format string
|
||||
|
||||
|
||||
all : Test
|
||||
all =
|
||||
describe "Format tests" <|
|
||||
[ describe "Date Format tests" <|
|
||||
List.map (makeTest << formatDateTest) dateTestData
|
||||
, describe "Time Format tests" <|
|
||||
List.map (makeTest << formatTimeTest) timeTestData
|
||||
]
|
||||
|
||||
|
||||
type alias TestTriple =
|
||||
( String, String, String )
|
||||
|
||||
|
||||
dateTestData : List TestTriple
|
||||
dateTestData =
|
||||
[ ( "numeric date", "12/08/2014", "%d/%m/%Y" )
|
||||
, ( "spelled out date", "Tuesday, August 12, 2014", "%A, %B %d, %Y" )
|
||||
, ( "time", expectedTime, "%I:%M:%S %p" )
|
||||
, ( "time no spaces", expectedTimeNoSpace, "%H%M%S" )
|
||||
, ( "literal %", expectedTimeWithLiteral, "%H%%%M" )
|
||||
, ( "padding modifiers", "08|8| 8|08", "%m|%-m|%_m|%0m" )
|
||||
]
|
||||
|
||||
|
||||
timeTestData : List TestTriple
|
||||
timeTestData =
|
||||
[ ( "time no spaces", expectedTimeNoSpace, "%H%M%S" )
|
||||
, ( "literal %", expectedTimeWithLiteral, "%H%%%M" )
|
||||
, ( "time colons", expectedTimeColons, "%H:%M" )
|
||||
, ( "time full colons", expectedFullTimeColons, "%H:%M:%S" )
|
||||
, ( "time with milliseconds", expectedTimeWithMilliSeconds, "%H:%M:%S:%L" )
|
||||
]
|
||||
|
||||
|
||||
expectedTimeWithLiteral =
|
||||
join "%" [ sampleHour, sampleMinute ]
|
||||
|
||||
|
||||
expectedTimeNoSpace =
|
||||
join "" [ sampleHour, sampleMinute, sampleMinute ]
|
||||
|
||||
|
||||
expectedTimeColons =
|
||||
join ":" [ sampleHour, sampleMinute ]
|
||||
|
||||
|
||||
expectedFullTimeColons =
|
||||
join ":" [ sampleHour, sampleMinute, sampleSecond ]
|
||||
|
||||
|
||||
expectedTimeWithMilliSeconds =
|
||||
join ":" [ sampleHour, sampleMinute, sampleSecond, sampleMilliSecond ]
|
||||
|
||||
|
||||
expectedTime =
|
||||
join ":" [ sampleHour, sampleMinute, sampleMinute ]
|
||||
++ (case Date.hour sampleDate < 12 of
|
||||
True ->
|
||||
" AM"
|
||||
|
||||
False ->
|
||||
" PM"
|
||||
)
|
||||
|
||||
|
||||
sampleDate : Date.Date
|
||||
sampleDate =
|
||||
Date.fromTime 1407819233012
|
||||
|
||||
|
||||
sampleTime : Time.Time
|
||||
sampleTime =
|
||||
Date.toTime sampleDate
|
||||
|
||||
|
||||
pad : Int -> Int -> String
|
||||
pad n =
|
||||
toString >> padLeft n '0'
|
||||
|
||||
|
||||
sampleHour : String
|
||||
sampleHour =
|
||||
Date.hour sampleDate
|
||||
|> pad 2
|
||||
|
||||
|
||||
sampleMinute : String
|
||||
sampleMinute =
|
||||
Date.minute sampleDate
|
||||
|> pad 2
|
||||
|
||||
|
||||
sampleSecond : String
|
||||
sampleSecond =
|
||||
Date.second sampleDate
|
||||
|> pad 2
|
||||
|
||||
|
||||
sampleMilliSecond : String
|
||||
sampleMilliSecond =
|
||||
Date.millisecond sampleDate
|
||||
|> pad 3
|
||||
|
||||
|
||||
formatSampleDate : String -> String
|
||||
formatSampleDate fstring =
|
||||
Date.Format.format fstring sampleDate
|
||||
|
||||
|
||||
formatSampleTime : String -> String
|
||||
formatSampleTime fstring =
|
||||
Time.Format.format fstring sampleTime
|
||||
|
||||
|
||||
formatDateTest : TestTriple -> TestTriple
|
||||
formatDateTest ( a, b, format ) =
|
||||
( a, b, formatSampleDate format )
|
||||
|
||||
|
||||
formatTimeTest : TestTriple -> TestTriple
|
||||
formatTimeTest ( a, b, format ) =
|
||||
( a, b, formatSampleTime format )
|
||||
|
||||
|
||||
makeTest : TestTriple -> Test
|
||||
makeTest ( described, expected, actual ) =
|
||||
test described <| \() -> Expect.equal actual expected
|
||||
16
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/tests/elm-package.json
vendored
Normal file
16
intro/part7/tests/elm-stuff/packages/mgold/elm-date-format/1.4.2/tests/elm-package.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "Tests for formatting dates with ease",
|
||||
"repository": "https://github.com/mgold/elm-date-format.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"../src",
|
||||
"."
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-community/elm-test": "4.2.0 <= v < 5.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
8
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/.gitignore
vendored
Normal file
8
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
elm-stuff
|
||||
elm.js
|
||||
index.html
|
||||
documentation.json
|
||||
|
||||
test/dieharder/elm*.txt
|
||||
test/dieharder/generate_files.js
|
||||
test/dieharder/raw_out.js
|
||||
30
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/LICENSE
vendored
Normal file
30
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/LICENSE
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
Copyright (c) 2015-2016, Max Goldstein
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of Max Goldstein nor the names of other
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
50
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/README.md
vendored
Normal file
50
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/README.md
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# Random.Pcg for Elm
|
||||
|
||||
> "The generation of random numbers is too important to be left to chance." – Robert R. Coveyou
|
||||
|
||||
An alternate random number generator built around four principles:
|
||||
|
||||
* **Statistical Quality.** If you use any seed less than 53,668 and generate one bool, it will be `True` – if you're
|
||||
using core's `Random` module. More sophisticated statistical tests spot patterns in the "random" numbers almost
|
||||
immediately. Would you want to trust the accuracy of your [fuzz
|
||||
tests](http://package.elm-lang.org/packages/elm-community/elm-test/latest/) to such a flawed algorithm? This library
|
||||
produces far less predictable and biased output, especially if you use thousands of random numbers. See
|
||||
`test/dieharder` for more details.
|
||||
|
||||
* **Useful features.** This library exports `constant` and `andMap`, which are conspicuously absent from core, along
|
||||
with other helpful functions for composing generators. Particularly interesting is `independentSeed`, which allows for
|
||||
lazy lists and isolated components to generate as much randomness as they need, when they need it.
|
||||
|
||||
* **Performance.** This library will generate floats about 3.5 times faster than core, and ints do not regress. These
|
||||
figures stand to improve pending some optimizations to the compiler. You can see the [full
|
||||
benchmark results](https://github.com/mgold/elm-random-pcg/issues/5#issuecomment-236398261).
|
||||
|
||||
* **Compatibility.** This library is a drop-in replacement for core's Random module. Specifically, you
|
||||
can replace `import Random` with `import Random.Pcg as Random` and everything will continue to work. (The one exception is third party
|
||||
libraries like [elm-random-extra](http://package.elm-lang.org/packages/NoRedInk/elm-random-extra/latest/Random-Extra).)
|
||||
|
||||
This is an implementation of [PCG](http://www.pcg-random.org/) by M. E. O'Neil. The generator is **not cryptographically
|
||||
secure**.
|
||||
|
||||
Please report bugs, feature requests, and other issues [on GitHub](https://github.com/mgold/elm-random-pcg/issues/new).
|
||||
|
||||
## Changelog (major versions only)
|
||||
### 5.0.0
|
||||
* Argument order of `andMap` flipped.
|
||||
|
||||
### 4.0.0
|
||||
* Upgraded for 0.18.
|
||||
* Argument order of `andThen` flipped.
|
||||
|
||||
### 3.0.0
|
||||
* Change implementation to use the RXS-M-SH variant of PCG. Now much faster and not much worse statistically.
|
||||
* Remove `initialSeed2`, since there are now only 32 bits of state.
|
||||
* `Random.Pcg.Interop.fission` has been changed to a (core) generator of (PCG) seeds.
|
||||
* Add `generate` to match core 4.x API. Implemented by Richard Feldman.
|
||||
|
||||
### 2.0.0
|
||||
* Upgraded for 0.17.
|
||||
* `generate` renamed `step` to match core 4.x API.
|
||||
* Module renamed `Random.Pcg` from `Random.PCG`.
|
||||
* `split` has been removed; use `independentSeed`.
|
||||
* `minInt` and `maxInt` values changed to match core.
|
||||
17
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/elm-package.json
vendored
Normal file
17
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/elm-package.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": "5.0.2",
|
||||
"summary": "A faster, more featureful, statistically better, & compatible random generator",
|
||||
"repository": "https://github.com/mgold/elm-random-pcg.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": [
|
||||
"Random.Pcg",
|
||||
"Random.Pcg.Interop"
|
||||
],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
848
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/src/Random/Pcg.elm
vendored
Normal file
848
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/src/Random/Pcg.elm
vendored
Normal file
@@ -0,0 +1,848 @@
|
||||
module Random.Pcg exposing (Generator, Seed, bool, int, float, oneIn, sample, pair, list, maybe, choice, choices, frequency, map, map2, map3, map4, map5, andMap, filter, constant, andThen, minInt, maxInt, step, generate, initialSeed, independentSeed, fastForward, toJson, fromJson)
|
||||
|
||||
{-| Generate psuedo-random numbers and values, by constructing
|
||||
[generators](#Generator) for them. There are a bunch of basic generators like
|
||||
[`bool`](#bool) and [`int`](#int) that you can build up into fancier generators
|
||||
with functions like [`list`](#list) and [`map`](#map).
|
||||
|
||||
You run a `Generator` by calling the [`step`](#step) function, which
|
||||
also takes a random [`Seed`](#Seed), and passes back a new seed. You should
|
||||
never use the same seed twice because you will get the same result! If you need
|
||||
random values over time, you should store the most recent seed in your model.
|
||||
Alternatively, use [`generate`](#generate) to obtain random values from the Elm
|
||||
runtime.
|
||||
|
||||
This is an implementation of [PCG](http://www.pcg-random.org/) by M. E. O'Neil,
|
||||
and is not cryptographically secure.
|
||||
|
||||
# Getting Started
|
||||
@docs initialSeed, step, generate
|
||||
|
||||
# Basic Generators
|
||||
@docs Generator, bool, int, float, oneIn, sample
|
||||
|
||||
# Combining Generators
|
||||
@docs pair, list, maybe, choice, choices, frequency
|
||||
|
||||
# Custom Generators
|
||||
@docs constant, map, map2, map3, map4, map5, andMap, andThen, filter
|
||||
|
||||
# Working With Seeds
|
||||
@docs Seed, independentSeed, fastForward, toJson, fromJson
|
||||
|
||||
# Constants
|
||||
@docs minInt, maxInt
|
||||
-}
|
||||
|
||||
import Bitwise
|
||||
import Json.Encode
|
||||
import Json.Decode
|
||||
import Task
|
||||
import Tuple
|
||||
import Time
|
||||
|
||||
|
||||
{-| A `Generator` is like a recipe for generating certain random values. So a
|
||||
`Generator Int` describes how to generate integers and a `Generator String`
|
||||
describes how to generate strings.
|
||||
-}
|
||||
type Generator a
|
||||
= Generator (Seed -> ( a, Seed ))
|
||||
|
||||
|
||||
{-| Generate a random value as specified by a given `Generator`, using a `Seed`
|
||||
and returning a new one.
|
||||
|
||||
In the following example, we are trying to generate numbers between 0 and 100
|
||||
with the `int 0 100` generator. Each time we call `generate` we need to provide
|
||||
a seed. This will produce a random number and a *new* seed to use if we want to
|
||||
run other generators later.
|
||||
|
||||
(x, seed1) = step (int 0 100) seed0
|
||||
(y, seed2) = step (int 0 100) seed1
|
||||
(z, seed3) = step (int 0 100) seed2
|
||||
[x, y, z] -- [85, 0, 38]
|
||||
|
||||
Notice that we use different seeds on each line. This is important! If you reuse
|
||||
the same seed, you get the same results.
|
||||
|
||||
(x, _) = step (int 0 100) seed0
|
||||
(y, _) = step (int 0 100) seed0
|
||||
(z, _) = step (int 0 100) seed0
|
||||
[x,y,z] -- [85, 85, 85]
|
||||
|
||||
As you can see, threading seeds through many calls to `step` is tedious and
|
||||
error-prone. That's why this library includes many functions to build more
|
||||
complicated generators, allowing you to call `step` only a small number of
|
||||
times.
|
||||
|
||||
Our example is best written as:
|
||||
|
||||
(xs, newSeed) = step (list 3 <| int 0 100) seed0
|
||||
xs -- [85, 0, 38]
|
||||
|
||||
-}
|
||||
step : Generator a -> Seed -> ( a, Seed )
|
||||
step (Generator generator) seed =
|
||||
generator seed
|
||||
|
||||
|
||||
{-| Create a Command that will generate random values according to the supplied
|
||||
`Generator`.
|
||||
|
||||
Think of this function as an alternative to `step`, since they both provide a
|
||||
way to actually get the random values that you want. This function frees you
|
||||
from worrying about seeds entirely, but as a tradeoff, you get your random
|
||||
values asynchronously, in their own Message. Additionally, due to constraints on
|
||||
third-party packages, it's possible that multiple commands sent at the same
|
||||
moment will return the same values.
|
||||
|
||||
You can also think of this function as an alternative to `independentSeed`,
|
||||
since they both allow you to use randomness in deeply nested components. In the
|
||||
case of this function, it's through sending Commands up the chain that you have
|
||||
to set up anyway.
|
||||
-}
|
||||
generate : (a -> msg) -> Generator a -> Cmd msg
|
||||
generate toMsg generator =
|
||||
Time.now
|
||||
|> Task.map (round >> initialSeed >> step generator >> Tuple.first)
|
||||
|> Task.perform toMsg
|
||||
|
||||
|
||||
{-| A `Seed` is the source of randomness in the whole system. It hides the
|
||||
current state of the random number generator.
|
||||
|
||||
Generators, not seeds, are the primary data structure for generating random
|
||||
values. Generators are much easier to chain and combine than functions that take
|
||||
and return seeds. Creating and managing seeds should happen "high up" in your
|
||||
program.
|
||||
-}
|
||||
type Seed
|
||||
= Seed Int Int
|
||||
|
||||
|
||||
{-| Initialize the state of the random number generator. The input should be
|
||||
a randomly chosen 32-bit integer. You can generate and copy random integers to
|
||||
create a reproducible psuedo-random generator.
|
||||
|
||||
$ node
|
||||
> Math.floor(Math.random()*0xFFFFFFFF)
|
||||
227852860
|
||||
|
||||
-- Elm
|
||||
seed0 : Seed
|
||||
seed0 = initialSeed 227852860
|
||||
|
||||
Alternatively, you can generate the random integers on page load and pass them
|
||||
through a port. The program will be different every time.
|
||||
|
||||
-- Elm
|
||||
port randomSeed : Int
|
||||
|
||||
seed0 : Seed
|
||||
seed0 = initialSeed randomSeed
|
||||
|
||||
-- JS
|
||||
Elm.ModuleName.fullscreen(
|
||||
{ randomSeed: Math.floor(Math.random()*0xFFFFFFFF) })
|
||||
|
||||
Either way, you should initialize a random seed only once. After that, whenever
|
||||
you use a seed, you'll get another one back.
|
||||
-}
|
||||
initialSeed : Int -> Seed
|
||||
initialSeed x =
|
||||
let
|
||||
(Seed state1 incr) =
|
||||
-- The magic constant is from Numerical Recipes and is inlined for perf.
|
||||
next (Seed 0 1013904223)
|
||||
|
||||
state2 =
|
||||
state1 + x |> Bitwise.shiftRightZfBy 0
|
||||
in
|
||||
next (Seed state2 incr)
|
||||
|
||||
|
||||
next : Seed -> Seed
|
||||
next (Seed state0 incr) =
|
||||
-- The magic constant is from Numerical Recipes and is inlined for perf.
|
||||
Seed ((state0 * 1664525) + incr |> Bitwise.shiftRightZfBy 0) incr
|
||||
|
||||
|
||||
|
||||
-- obtain a psuedorandom 32-bit integer
|
||||
|
||||
|
||||
peel : Seed -> Int
|
||||
peel (Seed state _) =
|
||||
-- This is the RXS-M-SH version of PCG, see section 6.3.4 of the paper
|
||||
-- and line 184 of pcg_variants.h in the 0.94 C implementation
|
||||
let
|
||||
word =
|
||||
((state |> Bitwise.shiftRightZfBy ((state |> Bitwise.shiftRightZfBy 28) + 4)) |> Bitwise.xor state) * 277803737
|
||||
in
|
||||
Bitwise.xor (word |> Bitwise.shiftRightZfBy 22) word
|
||||
|> Bitwise.shiftRightZfBy 0
|
||||
|
||||
|
||||
{-| Generate 32-bit integers in a given range, inclusive.
|
||||
|
||||
int 0 10 -- an integer between zero and ten
|
||||
int -5 5 -- an integer between -5 and 5
|
||||
|
||||
int minInt maxInt -- an integer in the widest range feasible
|
||||
|
||||
This function *can* produce values outside of the range [[`minInt`](#minInt),
|
||||
[`maxInt`](#maxInt)] but sufficient randomness is not guaranteed.
|
||||
|
||||
*Performance note:* This function will be ~1.5x faster if the range (i.e. `max - min + 1`) is a power of two. The
|
||||
effect will only be noticable if you are generating tens of thousands of random integers.
|
||||
|
||||
-}
|
||||
int : Int -> Int -> Generator Int
|
||||
int a b =
|
||||
Generator <|
|
||||
\seed0 ->
|
||||
let
|
||||
( lo, hi ) =
|
||||
if a < b then
|
||||
( a, b )
|
||||
else
|
||||
( b, a )
|
||||
|
||||
range =
|
||||
hi - lo + 1
|
||||
in
|
||||
-- fast path for power of 2
|
||||
if (range |> Bitwise.and (range - 1)) == 0 then
|
||||
( (peel seed0 |> Bitwise.and (range - 1) |> Bitwise.shiftRightZfBy 0) + lo, next seed0 )
|
||||
else
|
||||
let
|
||||
threshhold =
|
||||
-- essentially: period % max
|
||||
rem (-range |> Bitwise.shiftRightZfBy 0) range |> Bitwise.shiftRightZfBy 0
|
||||
|
||||
accountForBias : Seed -> ( Int, Seed )
|
||||
accountForBias seed =
|
||||
let
|
||||
x =
|
||||
peel seed
|
||||
|
||||
seedN =
|
||||
next seed
|
||||
in
|
||||
if x < threshhold then
|
||||
-- in practice this recurses almost never
|
||||
accountForBias seedN
|
||||
else
|
||||
( rem x range + lo, seedN )
|
||||
in
|
||||
accountForBias seed0
|
||||
|
||||
|
||||
bit53 =
|
||||
9007199254740992.0
|
||||
|
||||
|
||||
bit27 =
|
||||
134217728.0
|
||||
|
||||
|
||||
{-| Generate floats in a given range. The following example is a generator
|
||||
that produces numbers between 0 and 1.
|
||||
|
||||
probability : Generator Float
|
||||
probability =
|
||||
float 0 1
|
||||
-}
|
||||
float : Float -> Float -> Generator Float
|
||||
float min max =
|
||||
Generator <|
|
||||
\seed0 ->
|
||||
let
|
||||
-- Get 64 bits of randomness
|
||||
seed1 =
|
||||
next seed0
|
||||
|
||||
n0 =
|
||||
peel seed0
|
||||
|
||||
n1 =
|
||||
peel seed1
|
||||
|
||||
-- Get a uniformly distributed IEEE-754 double between 0.0 and 1.0
|
||||
hi =
|
||||
toFloat (n0 |> Bitwise.and 0x03FFFFFF) * 1.0
|
||||
|
||||
lo =
|
||||
toFloat (n1 |> Bitwise.and 0x07FFFFFF) * 1.0
|
||||
|
||||
val =
|
||||
((hi * bit27) + lo) / bit53
|
||||
|
||||
-- Scale it into our range
|
||||
range =
|
||||
abs (max - min)
|
||||
|
||||
scaled =
|
||||
val * range + min
|
||||
in
|
||||
( scaled, next seed1 )
|
||||
|
||||
|
||||
{-| Create a generator that produces boolean values with equal probability. This
|
||||
example simulates flipping three coins and checking if they're all heads.
|
||||
|
||||
threeHeads : Generator Bool
|
||||
threeHeads =
|
||||
map3 (\a b c -> a && b && c) bool bool bool
|
||||
-}
|
||||
bool : Generator Bool
|
||||
bool =
|
||||
map ((==) 1) (int 0 1)
|
||||
|
||||
|
||||
{-| The maximum value for randomly generated 32-bit ints.
|
||||
-}
|
||||
maxInt : Int
|
||||
maxInt =
|
||||
2147483647
|
||||
|
||||
|
||||
{-| The minimum value for randomly generated 32-bit ints.
|
||||
-}
|
||||
minInt : Int
|
||||
minInt =
|
||||
-2147483648
|
||||
|
||||
|
||||
{-| Create a pair of random values. A common use of this might be to generate
|
||||
a point in a certain 2D space. Imagine we have a collage that is 400 pixels
|
||||
wide and 200 pixels tall.
|
||||
|
||||
randomPoint : Generator (Int,Int)
|
||||
randomPoint =
|
||||
pair (int -200 200) (int -100 100)
|
||||
|
||||
-}
|
||||
pair : Generator a -> Generator b -> Generator ( a, b )
|
||||
pair genA genB =
|
||||
map2 (,) genA genB
|
||||
|
||||
|
||||
{-| Create a list of random values of a given length.
|
||||
|
||||
floatList : Generator (List Float)
|
||||
floatList =
|
||||
list 10 (float 0 1)
|
||||
|
||||
intList : Generator (List Int)
|
||||
intList =
|
||||
list 5 (int 0 100)
|
||||
|
||||
intPairs : Generator (List (Int, Int))
|
||||
intPairs =
|
||||
list 10 <| pair (int 0 100) (int 0 100)
|
||||
-}
|
||||
list : Int -> Generator a -> Generator (List a)
|
||||
list n (Generator generate) =
|
||||
Generator <|
|
||||
\seed ->
|
||||
listHelp [] n generate seed
|
||||
|
||||
|
||||
listHelp : List a -> Int -> (Seed -> ( a, Seed )) -> Seed -> ( List a, Seed )
|
||||
listHelp list n generate seed =
|
||||
if n < 1 then
|
||||
( list, seed )
|
||||
else
|
||||
let
|
||||
( value, newSeed ) =
|
||||
generate seed
|
||||
in
|
||||
listHelp (value :: list) (n - 1) generate newSeed
|
||||
|
||||
|
||||
{-| Create a generator that always produces the value provided. This is useful
|
||||
when creating complicated chained generators and you need to handle a simple
|
||||
case. It's also useful for the base case of recursive generators.
|
||||
-}
|
||||
constant : a -> Generator a
|
||||
constant value =
|
||||
Generator (\seed -> ( value, seed ))
|
||||
|
||||
|
||||
{-| Transform the values produced by a generator using a stateless function as a
|
||||
callback.
|
||||
|
||||
These examples show how to generate letters based on a basic integer generator.
|
||||
|
||||
lowercaseLetter : Generator Char
|
||||
lowercaseLetter =
|
||||
map (\n -> Char.fromCode (n + 97)) (int 0 25)
|
||||
|
||||
uppercaseLetter : Generator Char
|
||||
uppercaseLetter =
|
||||
map (\n -> Char.fromCode (n + 65)) (int 0 25)
|
||||
|
||||
-}
|
||||
map : (a -> b) -> Generator a -> Generator b
|
||||
map func (Generator genA) =
|
||||
Generator <|
|
||||
\seed0 ->
|
||||
let
|
||||
( a, seed1 ) =
|
||||
genA seed0
|
||||
in
|
||||
( func a, seed1 )
|
||||
|
||||
|
||||
{-| Combine two generators. This is useful when you have a function with two
|
||||
arguments that both need to be given random inputs.
|
||||
|
||||
pointInCircle : Float -> Generator (Float, Float)
|
||||
pointInCircle radius =
|
||||
let
|
||||
r = float 0 radius
|
||||
theta = map degrees (float 0 360)
|
||||
in
|
||||
map2 (curry fromPolar) r theta
|
||||
|
||||
-}
|
||||
map2 : (a -> b -> c) -> Generator a -> Generator b -> Generator c
|
||||
map2 func (Generator genA) (Generator genB) =
|
||||
Generator <|
|
||||
\seed0 ->
|
||||
let
|
||||
( a, seed1 ) =
|
||||
genA seed0
|
||||
|
||||
( b, seed2 ) =
|
||||
genB seed1
|
||||
in
|
||||
( func a b, seed2 )
|
||||
|
||||
|
||||
{-| Combine three generators. This could be used to produce random colors.
|
||||
|
||||
rgb : Generator Color.Color
|
||||
rgb =
|
||||
map3 Color.rgb (int 0 255) (int 0 255) (int 0 255)
|
||||
|
||||
hsl : Generator Color.Color
|
||||
hsl =
|
||||
map3 Color.hsl (map degrees (float 0 360)) (float 0 1) (float 0 1)
|
||||
-}
|
||||
map3 : (a -> b -> c -> d) -> Generator a -> Generator b -> Generator c -> Generator d
|
||||
map3 func (Generator genA) (Generator genB) (Generator genC) =
|
||||
Generator <|
|
||||
\seed0 ->
|
||||
let
|
||||
( a, seed1 ) =
|
||||
genA seed0
|
||||
|
||||
( b, seed2 ) =
|
||||
genB seed1
|
||||
|
||||
( c, seed3 ) =
|
||||
genC seed2
|
||||
in
|
||||
( func a b c, seed3 )
|
||||
|
||||
|
||||
{-| Combine four generators. This could be used to produce random transparent
|
||||
colors.
|
||||
|
||||
rgba : Generator Color.Color
|
||||
rgba =
|
||||
map4 Color.rgba (int 0 255) (int 0 255) (int 0 255) (float 0 1)
|
||||
-}
|
||||
map4 : (a -> b -> c -> d -> e) -> Generator a -> Generator b -> Generator c -> Generator d -> Generator e
|
||||
map4 func (Generator genA) (Generator genB) (Generator genC) (Generator genD) =
|
||||
Generator <|
|
||||
\seed0 ->
|
||||
let
|
||||
( a, seed1 ) =
|
||||
genA seed0
|
||||
|
||||
( b, seed2 ) =
|
||||
genB seed1
|
||||
|
||||
( c, seed3 ) =
|
||||
genC seed2
|
||||
|
||||
( d, seed4 ) =
|
||||
genD seed3
|
||||
in
|
||||
( func a b c d, seed4 )
|
||||
|
||||
|
||||
{-| Combine five generators.
|
||||
-}
|
||||
map5 : (a -> b -> c -> d -> e -> f) -> Generator a -> Generator b -> Generator c -> Generator d -> Generator e -> Generator f
|
||||
map5 func (Generator genA) (Generator genB) (Generator genC) (Generator genD) (Generator genE) =
|
||||
Generator <|
|
||||
\seed0 ->
|
||||
let
|
||||
( a, seed1 ) =
|
||||
genA seed0
|
||||
|
||||
( b, seed2 ) =
|
||||
genB seed1
|
||||
|
||||
( c, seed3 ) =
|
||||
genC seed2
|
||||
|
||||
( d, seed4 ) =
|
||||
genD seed3
|
||||
|
||||
( e, seed5 ) =
|
||||
genE seed4
|
||||
in
|
||||
( func a b c d e, seed5 )
|
||||
|
||||
|
||||
{-| Map over any number of generators.
|
||||
|
||||
randomPerson : Generator Person
|
||||
randomPerson =
|
||||
map person genFirstName
|
||||
|> andMap genLastName
|
||||
|> andMap genBirthday
|
||||
|> andMap genPhoneNumber
|
||||
|> andMap genAddress
|
||||
|> andMap genEmail
|
||||
-}
|
||||
andMap : Generator a -> Generator (a -> b) -> Generator b
|
||||
andMap =
|
||||
map2 (|>)
|
||||
|
||||
|
||||
{-| Chain random operations by providing a callback that accepts a
|
||||
randomly-generated value. The random value can be used to drive more randomness.
|
||||
|
||||
This example shows how we can use `andThen` to generate a list of random values
|
||||
*and* random length. Then we use `map` to apply a stateless function to that
|
||||
list. Assume we already have `genName : Generator String` defined.
|
||||
|
||||
authors : Generator String
|
||||
authors =
|
||||
int 1 5 -- number of authors
|
||||
|> andThen (\i -> list i genName)
|
||||
|> map (\ns ->
|
||||
case ns of
|
||||
[n] ->
|
||||
"Author: " ++ n
|
||||
n::ns ->
|
||||
"Authors: " ++ String.join ", " ns ++ " and " ++ n
|
||||
[] ->
|
||||
"This can't happen"
|
||||
)
|
||||
|
||||
If you find yourself calling `constant` in every branch of the callback, you can
|
||||
probably use `map` instead.
|
||||
-}
|
||||
andThen : (a -> Generator b) -> Generator a -> Generator b
|
||||
andThen callback (Generator generateA) =
|
||||
Generator <|
|
||||
\seed ->
|
||||
let
|
||||
( result, newSeed ) =
|
||||
generateA seed
|
||||
|
||||
(Generator generateB) =
|
||||
callback result
|
||||
in
|
||||
generateB newSeed
|
||||
|
||||
|
||||
{-| Filter a generator so that all generated values satisfy the given predicate.
|
||||
|
||||
evens : Generator Int
|
||||
evens =
|
||||
filter (\i -> i % 2 == 0) (int minInt maxInt)
|
||||
|
||||
**Warning:** If the predicate is unsatisfiable, the generator will not terminate, your
|
||||
application will hang with an infinite loop, and you will be sad. You should
|
||||
also avoid predicates that are merely very difficult to satisfy.
|
||||
|
||||
badCrashingGenerator =
|
||||
filter (\_ -> False) anotherGenerator
|
||||
|
||||
verySlowGenerator =
|
||||
filter (\i -> i % 2000 == 0) (int minInt maxInt)
|
||||
-}
|
||||
filter : (a -> Bool) -> Generator a -> Generator a
|
||||
filter predicate generator =
|
||||
Generator (retry generator predicate)
|
||||
|
||||
|
||||
retry : Generator a -> (a -> Bool) -> Seed -> ( a, Seed )
|
||||
retry generator predicate seed =
|
||||
let
|
||||
( candidate, newSeed ) =
|
||||
step generator seed
|
||||
in
|
||||
if predicate candidate then
|
||||
( candidate, newSeed )
|
||||
else
|
||||
retry generator predicate newSeed
|
||||
|
||||
|
||||
{-| Produce `True` one-in-n times on average.
|
||||
|
||||
Do not pass a value less then one to this function.
|
||||
|
||||
flippedHeads = oneIn 2
|
||||
rolled6 = oneIn 6
|
||||
criticalHit = oneIn 20
|
||||
-}
|
||||
oneIn : Int -> Generator Bool
|
||||
oneIn n =
|
||||
map ((==) 1) (int 1 n)
|
||||
|
||||
|
||||
{-| Given a list, choose an element uniformly at random. `Nothing` is only
|
||||
produced if the list is empty.
|
||||
|
||||
type Direction = North | South | East | West
|
||||
|
||||
direction : Generator Direction
|
||||
direction =
|
||||
sample [North, South, East, West]
|
||||
|> map (Maybe.withDefault North)
|
||||
|
||||
-}
|
||||
sample : List a -> Generator (Maybe a)
|
||||
sample =
|
||||
let
|
||||
find k ys =
|
||||
case ys of
|
||||
[] ->
|
||||
Nothing
|
||||
|
||||
z :: zs ->
|
||||
if k == 0 then
|
||||
Just z
|
||||
else
|
||||
find (k - 1) zs
|
||||
in
|
||||
\xs -> map (\i -> find i xs) (int 0 (List.length xs - 1))
|
||||
|
||||
|
||||
{-| Choose between two values with equal probability.
|
||||
|
||||
type Flip = Heads | Tails
|
||||
|
||||
coinFlip : Generator Flip
|
||||
coinFlip =
|
||||
choice Heads Tails
|
||||
-}
|
||||
choice : a -> a -> Generator a
|
||||
choice x y =
|
||||
map
|
||||
(\b ->
|
||||
if b then
|
||||
x
|
||||
else
|
||||
y
|
||||
)
|
||||
bool
|
||||
|
||||
|
||||
{-| Create a generator that chooses a generator from a list of generators
|
||||
with equal probability.
|
||||
|
||||
**Warning:** Do not pass an empty list or your program will crash! In practice
|
||||
this is usually not a problem since you pass a list literal.
|
||||
-}
|
||||
choices : List (Generator a) -> Generator a
|
||||
choices gens =
|
||||
frequency <| List.map (\g -> ( 1, g )) gens
|
||||
|
||||
|
||||
{-| Create a generator that chooses a generator from a list of generators
|
||||
based on the provided weight. The likelihood of a given generator being
|
||||
chosen is its weight divided by the total weight (which doesn't have to equal 1).
|
||||
|
||||
**Warning:** Do not pass an empty list or your program will crash! In practice
|
||||
this is usually not a problem since you pass a list literal.
|
||||
-}
|
||||
frequency : List ( Float, Generator a ) -> Generator a
|
||||
frequency pairs =
|
||||
let
|
||||
total =
|
||||
List.sum <| List.map (Tuple.first >> abs) pairs
|
||||
|
||||
pick choices n =
|
||||
case choices of
|
||||
( k, g ) :: rest ->
|
||||
if n <= k then
|
||||
g
|
||||
else
|
||||
pick rest (n - k)
|
||||
|
||||
_ ->
|
||||
Debug.crash "Empty list passed to Random.Pcg.frequency!"
|
||||
in
|
||||
float 0 total |> andThen (pick pairs)
|
||||
|
||||
|
||||
{-| Produce `Just` a value on `True`, and `Nothing` on `False`.
|
||||
|
||||
You can use `bool` or `oneIn n` for the first argument.
|
||||
-}
|
||||
maybe : Generator Bool -> Generator a -> Generator (Maybe a)
|
||||
maybe genBool genA =
|
||||
genBool
|
||||
|> andThen
|
||||
(\b ->
|
||||
if b then
|
||||
map Just genA
|
||||
else
|
||||
constant Nothing
|
||||
)
|
||||
|
||||
|
||||
{-| A generator that produces a seed that is independent of any other seed in
|
||||
the program. These seeds will generate their own unique sequences of random
|
||||
values. They are useful when you need an unknown amount of randomness *later*
|
||||
but can request only a fixed amount of randomness *now*.
|
||||
|
||||
Let's say you write a component that uses some randomness to initialize itself
|
||||
and then never needs randomness again. You can easily write a `Generator
|
||||
Component` by mapping over the generators it needs. But if component requires
|
||||
randomness after initialization, it should keep its own independent seed, which
|
||||
it can get by mapping over *this* generator.
|
||||
|
||||
type alias Component = { seed : Seed }
|
||||
|
||||
genComponent : Generator Component
|
||||
genComponent = map Component independentSeed
|
||||
|
||||
If you have a lot of components, you can initialize them like so:
|
||||
|
||||
genComponents : List (Seed -> a) -> Generator (List a)
|
||||
genComponents constructors =
|
||||
list (List.length constructors) independentSeed
|
||||
|> map (List.map2 (<|) constructors)
|
||||
|
||||
The independent seeds are extremely likely to be distinct for all practical
|
||||
purposes. However, it is not proven that there are no pathological cases.
|
||||
-}
|
||||
independentSeed : Generator Seed
|
||||
independentSeed =
|
||||
Generator <|
|
||||
\seed0 ->
|
||||
let
|
||||
gen =
|
||||
int 0 0xFFFFFFFF
|
||||
|
||||
( ( state, b, c ), seed1 ) =
|
||||
step (map3 (,,) gen gen gen) seed0
|
||||
|
||||
{--
|
||||
Although it probably doesn't hold water theoretically, xor two
|
||||
random numbers to make an increment less likely to be
|
||||
pathological. Then make sure that it's odd, which is required.
|
||||
Finally step it once before use.
|
||||
--}
|
||||
incr =
|
||||
(Bitwise.xor b c) |> Bitwise.or 1 |> Bitwise.shiftRightZfBy 0
|
||||
in
|
||||
( seed1, next <| Seed state incr )
|
||||
|
||||
|
||||
mul32 : Int -> Int -> Int
|
||||
mul32 a b =
|
||||
-- multiply 32-bit integers without overflow
|
||||
let
|
||||
ah =
|
||||
(a |> Bitwise.shiftRightZfBy 16) |> Bitwise.and 0xFFFF
|
||||
|
||||
al =
|
||||
Bitwise.and a 0xFFFF
|
||||
|
||||
bh =
|
||||
(b |> Bitwise.shiftRightZfBy 16) |> Bitwise.and 0xFFFF
|
||||
|
||||
bl =
|
||||
Bitwise.and b 0xFFFF
|
||||
in
|
||||
-- The Bitwise.or could probably be replaced with shiftRightZfBy but I'm not positive?
|
||||
(al * bl) + (((ah * bl + al * bh) |> Bitwise.shiftLeftBy 16) |> Bitwise.shiftRightZfBy 0) |> Bitwise.or 0
|
||||
|
||||
|
||||
{-| Fast forward a seed the given number of steps, which may be negative (the
|
||||
seed will be "rewound"). This allows a single seed to serve as a random-access
|
||||
lookup table of random numbers. (To be sure no one else uses the seed, use
|
||||
`step independentSeed` to split off your own.)
|
||||
|
||||
diceRollTable : Int -> Int
|
||||
diceRollTable i =
|
||||
fastForward i mySeed |> step (int 1 6) |> Tuple.first
|
||||
-}
|
||||
fastForward : Int -> Seed -> Seed
|
||||
fastForward delta0 (Seed state0 incr) =
|
||||
let
|
||||
helper : Int -> Int -> Int -> Int -> Int -> Bool -> ( Int, Int )
|
||||
helper accMult accPlus curMult curPlus delta repeat =
|
||||
let
|
||||
( accMult_, accPlus_ ) =
|
||||
if Bitwise.and delta 1 == 1 then
|
||||
( mul32 accMult curMult
|
||||
, mul32 accPlus curMult + curPlus |> Bitwise.shiftRightZfBy 0
|
||||
)
|
||||
else
|
||||
( accMult, accPlus )
|
||||
|
||||
curPlus_ =
|
||||
mul32 (curMult + 1) curPlus
|
||||
|
||||
curMult_ =
|
||||
mul32 curMult curMult
|
||||
|
||||
newDelta =
|
||||
-- divide by 2
|
||||
delta |> Bitwise.shiftRightZfBy 1
|
||||
in
|
||||
if newDelta == 0 then
|
||||
if delta0 < 0 && repeat then
|
||||
-- if passed a negative number, negate everything once
|
||||
helper accMult_ accPlus_ curMult_ curPlus_ -1 False
|
||||
else
|
||||
( accMult_, accPlus_ )
|
||||
else
|
||||
helper accMult_ accPlus_ curMult_ curPlus_ newDelta repeat
|
||||
|
||||
( accMultFinal, accPlusFinal ) =
|
||||
-- magic constant same as in next
|
||||
helper 1 0 1664525 incr delta0 True
|
||||
in
|
||||
Seed (mul32 accMultFinal state0 + accPlusFinal |> Bitwise.shiftRightZfBy 0) incr
|
||||
|
||||
|
||||
{-| Serialize a seed as a [JSON
|
||||
value](http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Encode#Value)
|
||||
to be sent out a port, stored in local storage, and so on. The seed can be
|
||||
recovered using `fromJson`.
|
||||
|
||||
Do not inspect or change the resulting JSON value.
|
||||
-}
|
||||
toJson : Seed -> Json.Encode.Value
|
||||
toJson (Seed state incr) =
|
||||
Json.Encode.list [ Json.Encode.int state, Json.Encode.int incr ]
|
||||
|
||||
|
||||
{-| A JSON decoder that can recover seeds encoded using `toJson`. Alternatively,
|
||||
pass an integer to create a seed using `initialSeed`.
|
||||
|
||||
Json.Decode.decodeValue fromJson (toJson mySeed) == Ok mySeed
|
||||
-}
|
||||
fromJson : Json.Decode.Decoder Seed
|
||||
fromJson =
|
||||
Json.Decode.oneOf
|
||||
[ Json.Decode.map2 Seed
|
||||
(Json.Decode.index 0 Json.Decode.int)
|
||||
(Json.Decode.index 1 Json.Decode.int)
|
||||
, Json.Decode.map initialSeed Json.Decode.int
|
||||
]
|
||||
29
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/src/Random/Pcg/Interop.elm
vendored
Normal file
29
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/src/Random/Pcg/Interop.elm
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
module Random.Pcg.Interop exposing (fission)
|
||||
|
||||
{-| Provides a function to create a PCG seed from a seed in the core library.
|
||||
This is useful for library writers who need a splittable or most robust PRNG but
|
||||
don't want to require client code to use the PCG implementation.
|
||||
|
||||
```elm
|
||||
import Random
|
||||
import Random.Pcg
|
||||
import Random.Pcg.Interop as Random.Pcg
|
||||
```
|
||||
|
||||
@docs fission
|
||||
-}
|
||||
|
||||
import Random
|
||||
import Random.Pcg
|
||||
|
||||
|
||||
{-| Use the core library's random seed to produce a PCG random seed.
|
||||
|
||||
It seems that the package website doesn't show modules in type annotations, so here it is in full:
|
||||
|
||||
fission : Random.Generator (Random.Pcg.Seed)
|
||||
|
||||
-}
|
||||
fission : Random.Generator Random.Pcg.Seed
|
||||
fission =
|
||||
Random.int 0 0xFFFFFFFF |> Random.map Random.Pcg.initialSeed
|
||||
4
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/README.md
vendored
Normal file
4
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/README.md
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Random.Pcg Tests
|
||||
|
||||
The tests in this directory are one-off simple programs to confirm that certain functions aren't obviously wrong.
|
||||
Heavyweight statistical tests are under `dieharder`. Benchmarks (using a 0.16 benchmarking lib) are in `benchmark`.
|
||||
26
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/Bench/Native.elm
vendored
Normal file
26
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/Bench/Native.elm
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
module Bench.Native exposing (..)
|
||||
|
||||
import Native.Benchmark
|
||||
|
||||
|
||||
type Benchmark
|
||||
= Benchmark
|
||||
|
||||
|
||||
type BenchmarkSuite
|
||||
= BenchmarkSuite
|
||||
|
||||
|
||||
bench : String -> (() -> a) -> Benchmark
|
||||
bench =
|
||||
Native.Benchmark.bench
|
||||
|
||||
|
||||
suite : String -> List (Benchmark) -> BenchmarkSuite
|
||||
suite =
|
||||
Native.Benchmark.suite
|
||||
|
||||
|
||||
run : List (BenchmarkSuite) -> b -> b
|
||||
run =
|
||||
Native.Benchmark.run
|
||||
45
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/Bencher.elm
vendored
Normal file
45
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/Bencher.elm
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
module Main exposing (main)
|
||||
|
||||
import Html
|
||||
import Html.App
|
||||
import Bench.Native as Benchmark
|
||||
import Bench.Native exposing (Benchmark, BenchmarkSuite, bench, suite)
|
||||
import Random.Pcg as Ran
|
||||
|
||||
|
||||
main : Program Never
|
||||
main =
|
||||
Html.App.beginnerProgram
|
||||
{ model = ()
|
||||
, update = \_ _ -> ()
|
||||
, view = \() -> Html.text "Done!"
|
||||
}
|
||||
|> Benchmark.run [ mySuite ]
|
||||
|
||||
|
||||
seed : Ran.Seed
|
||||
seed =
|
||||
Ran.initialSeed 141053960
|
||||
|
||||
|
||||
n =
|
||||
1000
|
||||
|
||||
|
||||
mySuite : BenchmarkSuite
|
||||
mySuite =
|
||||
suite
|
||||
"Random number suite"
|
||||
[ bench "flip a coin" (\_ -> Ran.step Ran.bool seed)
|
||||
, bench ("flip " ++ toString n ++ " coins") (\_ -> Ran.step (Ran.list n Ran.bool) seed)
|
||||
, bench "generate an integer 0-4094" (\_ -> Ran.step (Ran.int 0 4094) seed)
|
||||
, bench "generate an integer 0-4095" (\_ -> Ran.step (Ran.int 0 4095) seed)
|
||||
, bench "generate an integer 0-4096" (\_ -> Ran.step (Ran.int 0 4096) seed)
|
||||
, bench "generate a massive integer" (\_ -> Ran.step (Ran.int 0 4294967295) seed)
|
||||
, bench "generate a percentage" (\_ -> Ran.step (Ran.float 0 1) seed)
|
||||
, bench ("generate " ++ toString n ++ " percentages") (\_ -> Ran.step (Ran.list n (Ran.float 0 1)) seed)
|
||||
, bench "generate a float 0-4094" (\_ -> Ran.step (Ran.float 0 4094) seed)
|
||||
, bench "generate a float 0-4095" (\_ -> Ran.step (Ran.float 0 4095) seed)
|
||||
, bench "generate a float 0-4096" (\_ -> Ran.step (Ran.float 0 4096) seed)
|
||||
, bench "generate a massive float" (\_ -> Ran.step (Ran.float 0 4294967295) seed)
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
var _user$project$Native_Benchmark = (function () {
|
||||
function bench(name, fn) {
|
||||
return {
|
||||
name: name,
|
||||
fn: fn
|
||||
}
|
||||
}
|
||||
|
||||
function suite(name, fnList) {
|
||||
var fns = _elm_lang$core$Native_List.toArray(fnList),
|
||||
suite = new Benchmark.Suite(name),
|
||||
i, curr;
|
||||
|
||||
for (i = 0; i < fns.length; i++) {
|
||||
curr = fns[i];
|
||||
suite = suite.add(curr.name, curr.fn);
|
||||
}
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
function run(suiteList, program) {
|
||||
var suites = _elm_lang$core$Native_List.toArray(suiteList),
|
||||
i;
|
||||
|
||||
for (i = 0; i < suites.length; i++) {
|
||||
suites[i].on('start', function () {
|
||||
console.log('Starting ' + this.name + ' suite.');
|
||||
}).on('cycle', function (event) {
|
||||
console.log(String(event.target));
|
||||
}).on('complete', function () {
|
||||
console.log('Done with ' + this.name + ' suite.');
|
||||
}).run();
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
return {
|
||||
bench: F2(bench),
|
||||
suite: F2(suite),
|
||||
run: F2(run)
|
||||
};
|
||||
})()
|
||||
14
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/README.md
vendored
Normal file
14
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/README.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Benchmarks for Random.Pcg
|
||||
|
||||
These benchmarks are possible thanks to Robin Heggelund Hansen's work benchmarking [collections-ng](https://github.com/Skinney/collections-ng).
|
||||
|
||||
To run them yourself, first download the vendor files (you only need to do this once):
|
||||
```
|
||||
mkdir vendor
|
||||
cd vendor
|
||||
wget https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js
|
||||
wget https://cdn.jsdelivr.net/benchmarkjs/2.1.0/benchmark.js
|
||||
```
|
||||
|
||||
Then adjust the import of `Random` in `Bencher.elm` to control which library is being benchmarked. Finally run `sh prep-bench.sh` then
|
||||
`elm-reactor` in this directory and open `run-benchmarks.html`.
|
||||
17
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/elm-package.json
vendored
Normal file
17
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/elm-package.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"summary": "Benchmarking suite for Random.Pcg",
|
||||
"repository": "https://github.com/user/project.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
".",
|
||||
"../../src"
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"native-modules": true,
|
||||
"dependencies": {
|
||||
"elm-lang/core": "4.0.0 <= v < 5.0.0",
|
||||
"elm-lang/html": "1.1.0 <= v < 2.0.0"
|
||||
},
|
||||
"elm-version": "0.17.0 <= v < 0.18.0"
|
||||
}
|
||||
5
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/prep-bench.sh
vendored
Normal file
5
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/benchmark/prep-bench.sh
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
elm-make --yes --output bench.js Bencher.elm
|
||||
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html><head><meta charset="UTF-8"><title>Main</title><style>html,head,body { padding:0; margin:0; }
|
||||
body { font-family: calibri, helvetica, arial, sans-serif; }</style>
|
||||
<script type="text/javascript" src="vendor/lodash.min.js"></script>
|
||||
<script type="text/javascript" src="vendor/benchmark.js"></script>
|
||||
<script type="text/javascript" src="bench.js"></script>
|
||||
</head><body>Check console for output... <script type="text/javascript">Elm.Main.fullscreen()</script></body></html>
|
||||
40
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/bounds.elm
vendored
Normal file
40
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/bounds.elm
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
module Bounds exposing (..)
|
||||
|
||||
{-| Demonstrate that, after creating ten million floats between 0 and 1, all
|
||||
indeed fall inside that range. If you try this test with core (4.x) Random, it
|
||||
will produce at least one value less than zero! This could have catastrophic
|
||||
effects if you take the log or square root of this value, although more likely
|
||||
it will just propogate NaN through your program.
|
||||
-}
|
||||
|
||||
import Random.Pcg as Random
|
||||
import Html
|
||||
import Html.App
|
||||
|
||||
|
||||
n =
|
||||
10000000
|
||||
|
||||
|
||||
seed0 : Random.Seed
|
||||
seed0 =
|
||||
Random.initialSeed 628318530
|
||||
|
||||
|
||||
samples : List Float
|
||||
samples =
|
||||
Random.step (Random.list n (Random.float 0 1)) seed0 |> fst
|
||||
|
||||
|
||||
range : ( Maybe Float, Maybe Float )
|
||||
range =
|
||||
( List.minimum samples, List.maximum samples )
|
||||
|
||||
|
||||
main : Program Never
|
||||
main =
|
||||
Html.App.beginnerProgram
|
||||
{ model = ()
|
||||
, update = \_ _ -> ()
|
||||
, view = \() -> Html.text <| toString <| range
|
||||
}
|
||||
58
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/Dieharder.elm
vendored
Normal file
58
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/Dieharder.elm
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import String
|
||||
import Task exposing (Task)
|
||||
import Random.Pcg as Random
|
||||
|
||||
import Console exposing (IO)
|
||||
|
||||
name = "elm-random-pcg"
|
||||
|
||||
n = 2e6 |> round
|
||||
seed0 = 42
|
||||
bound = {lo = 0, hi = 0xFFFFFFFF}
|
||||
|
||||
header : IO ()
|
||||
header =
|
||||
Console.putStr <| "# " ++ name ++ "\n# seed: " ++ toString seed0 ++ "\ntype: d\ncount: " ++
|
||||
toString (12*n) ++ "\nnumbit: 32"
|
||||
|
||||
body : List Int -> IO ()
|
||||
body ints =
|
||||
Console.putStr "\n"
|
||||
`Console.seq`
|
||||
Console.putStr (List.map (toString >> String.padLeft 10 ' ') ints |> String.join "\n")
|
||||
|
||||
core : Random.Seed -> (List Int, Random.Seed)
|
||||
core seed =
|
||||
let gen = Random.list n (Random.int bound.lo bound.hi)
|
||||
in Random.step gen seed
|
||||
|
||||
run1 : Random.Seed -> IO Random.Seed
|
||||
run1 seed =
|
||||
let (ints, seed2) = core seed
|
||||
in body ints |> Console.map (\_ -> seed2)
|
||||
|
||||
job : IO ()
|
||||
job =
|
||||
header
|
||||
`Console.seq`
|
||||
run1 (Random.initialSeed seed0)
|
||||
`Console.andThen` run1
|
||||
`Console.andThen` run1
|
||||
`Console.andThen` run1
|
||||
|
||||
`Console.andThen` run1
|
||||
`Console.andThen` run1
|
||||
`Console.andThen` run1
|
||||
|
||||
`Console.andThen` run1
|
||||
`Console.andThen` run1
|
||||
`Console.andThen` run1
|
||||
|
||||
`Console.andThen` run1
|
||||
`Console.andThen` run1
|
||||
`Console.seq`
|
||||
Console.exit 0
|
||||
|
||||
|
||||
port io : Signal (Task x ())
|
||||
port io = Console.run job
|
||||
27
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/README.md
vendored
Normal file
27
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/README.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Dieharder tests for Random.Pcg
|
||||
|
||||
**These tests rely on a library that has not been update for 0.17.**
|
||||
|
||||
The purpose of testing the random number generator is twofold: one, show the deficiencies in the core implementation;
|
||||
two, show the correctness of the Pcg implementation *in Elm*. Because we are testing the Elm implementation, not the Pcg
|
||||
algorithm, we must feed dieharder a file of already-generated random numbers. I've seen sources recommending 10 million
|
||||
random numbers; these tests use 24 million, but even so the files are "rewound", as many as 2500 times on later tests.
|
||||
|
||||
For the original 19 diehard tests, the core fails 9 tests while Pcg fails none. (One test resulted in "weak" but further
|
||||
investigation resulted in passing; we expect this on one test in 100). On the entire battery, core passes 29, fails 75,
|
||||
and is weak in 10. Pcg passes 82, fails 24, and is weak in 8. Some of Pcg's strength may be attributed to its 64 bits of
|
||||
state, compared to core's 32, but this does not excuse failing the less-comprehensive diehard tests. Conversely, many of
|
||||
the failures can be attributed to reusing pre-generated random numbers.
|
||||
|
||||
The source Elm is `Dieharder.elm`. Because the tests require more random numbers than can be stored in memory, they
|
||||
output chunks of 2 million at a time. In order to reuse the code, `compile.sh` rewrites the file to change the Random
|
||||
implementation. It also writes out the `.txt` data files, and then runs dieharder, logging the results.
|
||||
|
||||
The result log files have been committed to version control; I would have liked to commit the data files but they're
|
||||
huge, and only take a few minutes to generate. You are free to alter the random seed in the Elm code, and rerun the
|
||||
tests with `sh compile` (which takes several hours to complete). That said, I encourage you to run it long enough to see
|
||||
core fail the birthday test, after only five or six seconds of scrutiny. (The `dieharder` tool is available through most
|
||||
package managers. Once the data files are generated, try `time dieharder -g 202 -f elm-core-random.txt -d 0`.)
|
||||
|
||||
The Pcg paper uses the TestU01 (e.g. BigCrush) suite; I'm using dieharder since it was easier to get to work
|
||||
reading from a file.
|
||||
24
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/compile.sh
vendored
Normal file
24
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/compile.sh
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -f elm-core-random.txt ]; then
|
||||
sed -i.bak 's/import Random.Pcg as Random/import Random/g' Dieharder.elm
|
||||
sed -i.bak 's/elm-random-pcg/elm-core-random/g' Dieharder.elm
|
||||
elm make Dieharder.elm --output=raw_out.js
|
||||
sh elm-io.sh raw_out.js generate_files.js
|
||||
echo "Generating elm-core-random.txt..."
|
||||
node generate_files.js > elm-core-random.txt
|
||||
dieharder -g 202 -f elm-core-random.txt -a | tee dieharder-core.log
|
||||
fi
|
||||
|
||||
if [ ! -f elm-random-pcg.txt ]; then
|
||||
sed -i.bak 's/import Random$/import Random.Pcg as Random/g' Dieharder.elm
|
||||
sed -i.bak 's/elm-core-random/elm-random-pcg/g' Dieharder.elm
|
||||
elm make Dieharder.elm --output=raw_out.js
|
||||
sh elm-io.sh raw_out.js generate_files.js
|
||||
echo "Generating elm-random-pcg.txt..."
|
||||
node generate_files.js > elm-random-pcg.txt
|
||||
dieharder -g 202 -f elm-random-pcg.txt -a | tee dieharder-pcg.log
|
||||
fi
|
||||
|
||||
19
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/elm-io.sh
vendored
Normal file
19
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/elm-io.sh
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Script for use with the Console library to allow Elm to run on Node.
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Usage: $0 <generated-js-file> <output-file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
read -d '' handler <<- EOF
|
||||
(function(){
|
||||
if (typeof Elm === "undefined") { throw "elm-io config error: Elm is not defined. Make sure you call elm-io with a real Elm output file"}
|
||||
if (typeof Elm.Main === "undefined" ) { throw "Elm.Main is not defined, make sure your module is named Main." };
|
||||
var worker = Elm.worker(Elm.Main);
|
||||
})();
|
||||
EOF
|
||||
|
||||
cat $1 > $2
|
||||
echo "$handler" >> $2
|
||||
15
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/elm-package.json
vendored
Normal file
15
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/dieharder/elm-package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"summary": "Dieharder tests for elm-random-pcg",
|
||||
"repository": "https://github.com/user/project.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
".", "../../src"
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "3.0.0 <= v < 4.0.0",
|
||||
"laszlopandy/elm-console": "1.0.3 <= v < 2.0.0"
|
||||
},
|
||||
"elm-version": "0.16.0 <= v < 0.17.0"
|
||||
}
|
||||
15
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/elm-package.json
vendored
Normal file
15
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/elm-package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"summary": "Miscellaneous tests for elm-pcg-random",
|
||||
"repository": "https://github.com/user/project.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
".", "../src"
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "4.0.3 <= v < 5.0.0",
|
||||
"elm-lang/html": "1.1.0 <= v < 2.0.0"
|
||||
},
|
||||
"elm-version": "0.17.1 <= v < 0.18.0"
|
||||
}
|
||||
61
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/fastForward.elm
vendored
Normal file
61
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/fastForward.elm
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
module FastForwardTest exposing (..)
|
||||
|
||||
{-| Compares the outputs of seeds created using the ordinary sequential stepping method,
|
||||
and those created using the `fastForward` function. Note that we compare output, not the
|
||||
seeds themselves, because somestimes the states get confused between signed and unsigned--
|
||||
this has no effect on the psuedo-random output. (Edit July 2016: not sure if that's true
|
||||
anymore...)
|
||||
-}
|
||||
|
||||
import Random.Pcg as Random
|
||||
import Html
|
||||
import Html.App
|
||||
|
||||
|
||||
n =
|
||||
100000
|
||||
|
||||
|
||||
seed0 : Random.Seed
|
||||
seed0 =
|
||||
Random.initialSeed 628318530
|
||||
|
||||
|
||||
stepped : List Random.Seed
|
||||
stepped =
|
||||
List.scanl
|
||||
(\_ oldSeed -> Random.step Random.bool oldSeed |> snd)
|
||||
seed0
|
||||
[1..n]
|
||||
|
||||
|
||||
fastForwarded : List Random.Seed
|
||||
fastForwarded =
|
||||
List.map
|
||||
(\i -> Random.fastForward i seed0)
|
||||
[0..n]
|
||||
|
||||
|
||||
gen =
|
||||
Random.int 1 10000
|
||||
|
||||
|
||||
generate seed =
|
||||
Random.step gen seed |> fst
|
||||
|
||||
|
||||
bools =
|
||||
List.map2
|
||||
(\seed1 seed2 -> generate seed1 == generate seed2)
|
||||
stepped
|
||||
fastForwarded
|
||||
|> List.all identity
|
||||
|
||||
|
||||
main : Program Never
|
||||
main =
|
||||
Html.App.beginnerProgram
|
||||
{ model = ()
|
||||
, update = \_ _ -> ()
|
||||
, view = \() -> Html.text <| toString <| bools
|
||||
}
|
||||
35
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/filterTest.elm
vendored
Normal file
35
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/filterTest.elm
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
module FilterTest exposing (..)
|
||||
|
||||
import Html exposing (Html)
|
||||
import Random.Pcg as Random
|
||||
|
||||
|
||||
{-| This test checks that very difficult-to-satisfy filters do not result in a stack
|
||||
overflow (just run slowly). The test will take several seconds to run!
|
||||
-}
|
||||
main : Html Never
|
||||
main =
|
||||
let
|
||||
-- Try 'predicate i = False' to verify that the test hangs instead of
|
||||
-- crashing with a stack overflow (indicating that tail recursion has
|
||||
-- been properly optimized into a loop, which in this case happens to
|
||||
-- be infinite).
|
||||
predicate i =
|
||||
i % 1000000 == 0
|
||||
|
||||
divisibleNumberGenerator =
|
||||
Random.filter predicate (Random.int Random.minInt Random.maxInt)
|
||||
|
||||
listGenerator =
|
||||
Random.list 10 divisibleNumberGenerator
|
||||
|
||||
initialSeed =
|
||||
Random.initialSeed 1234
|
||||
|
||||
generatedList =
|
||||
fst (Random.step listGenerator initialSeed)
|
||||
in
|
||||
-- You can verify that everything is working by observing that the generated
|
||||
-- sum is in fact divisible by the chosen divisor (e.g. for a divisor of
|
||||
-- 1000000 the sum should always have six trailing zeros)
|
||||
Html.text (toString (List.sum generatedList))
|
||||
40
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/independentSeedTest.elm
vendored
Normal file
40
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/independentSeedTest.elm
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
module IndependentSeedTest exposing (..)
|
||||
|
||||
import Html exposing (Html)
|
||||
import Random.Pcg as Random exposing (Generator)
|
||||
import Debug
|
||||
|
||||
|
||||
{-| This test ensures that the 'independentSeed' generator actually produces
|
||||
valid random seeds that can be stepped properly to produce distinct values. If
|
||||
there is an error in 'independentSeed', at some point a seed such as 'Seed 0
|
||||
0' will be produced which when stepped will yield itself, resulting in an
|
||||
infinite loop within 'filter' (since it will internally just keep generating
|
||||
the same value over and over again).
|
||||
-}
|
||||
main : Html Never
|
||||
main =
|
||||
let
|
||||
initialSeed =
|
||||
Random.initialSeed 1234
|
||||
|
||||
seedListGenerator =
|
||||
Random.list 1000 Random.independentSeed
|
||||
|
||||
randomSeeds =
|
||||
fst (Random.step seedListGenerator initialSeed)
|
||||
|
||||
isDivisible i =
|
||||
let
|
||||
_ =
|
||||
Debug.log "i" i
|
||||
in
|
||||
i /= 0 && i % 10 == 0
|
||||
|
||||
divisibleNumberGenerator =
|
||||
Random.filter isDivisible (Random.int Random.minInt Random.maxInt)
|
||||
|
||||
divisibleNumbers =
|
||||
List.map (Random.step divisibleNumberGenerator >> fst) randomSeeds
|
||||
in
|
||||
Html.text (toString (List.sum divisibleNumbers))
|
||||
60
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/listTest.elm
vendored
Normal file
60
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/listTest.elm
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
module ListTest exposing (..)
|
||||
|
||||
{-| The central limit theorem states that if you sample any distribution and take the mean, and do that many times,
|
||||
those means will be on a standard distribution.
|
||||
|
||||
That's exactly what this test does, using an independent seed. Judging how "good" the distribution is versus how good it
|
||||
"should" be is beyond the scope of this example. This test is really to show that independent seeds aren't *trivially*
|
||||
wrong.
|
||||
-}
|
||||
|
||||
import Dict exposing (Dict)
|
||||
import Random.Pcg as Random
|
||||
import Html
|
||||
import Html.App
|
||||
|
||||
|
||||
seed0 : Random.Seed
|
||||
seed0 =
|
||||
Random.initialSeed 628318530 |> Random.step Random.independentSeed |> snd
|
||||
|
||||
|
||||
gen =
|
||||
Random.int 1 6
|
||||
|> Random.list 15
|
||||
|> Random.map mean
|
||||
|> Random.map (\x -> round (10 * x))
|
||||
|> Random.list 800
|
||||
|> Random.map toMultiSet
|
||||
|
||||
|
||||
mean : List Int -> Float
|
||||
mean xs =
|
||||
toFloat (List.sum xs) / toFloat (List.length xs)
|
||||
|
||||
|
||||
toMultiSet : List Int -> Dict Int Int
|
||||
toMultiSet list =
|
||||
let
|
||||
helper xs d =
|
||||
case xs of
|
||||
[] ->
|
||||
d
|
||||
|
||||
x :: xs ->
|
||||
helper xs <| Dict.insert x (Dict.get x d |> Maybe.withDefault 0 |> (+) 1) d
|
||||
in
|
||||
helper list Dict.empty
|
||||
|
||||
|
||||
generated =
|
||||
Random.step gen seed0 |> fst
|
||||
|
||||
|
||||
main : Program Never
|
||||
main =
|
||||
Html.App.beginnerProgram
|
||||
{ model = ()
|
||||
, update = \_ _ -> ()
|
||||
, view = \() -> Html.text <| toString <| generated
|
||||
}
|
||||
7
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/port/README.md
vendored
Normal file
7
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/port/README.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# Port test
|
||||
|
||||
```
|
||||
elm make Test.elm --output=elm.js
|
||||
```
|
||||
|
||||
This shows how to hook up ports to the random number generator to produce different values each time.
|
||||
13
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/port/Test.elm
vendored
Normal file
13
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/port/Test.elm
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
module Test where
|
||||
|
||||
import Graphics.Element exposing (show)
|
||||
import Random.Pcg as Random
|
||||
|
||||
port randomSeed : (Int, Int)
|
||||
|
||||
seed0 : Random.Seed
|
||||
seed0 = (uncurry Random.initialSeed2) randomSeed
|
||||
|
||||
gen = Random.list 32 (Random.int 1 6)
|
||||
|
||||
main = show <| fst <| Random.generate gen seed0
|
||||
14
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/port/elm-package.json
vendored
Normal file
14
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/port/elm-package.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "helpful summary of your project, less than 80 characters",
|
||||
"repository": "https://github.com/user/project.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
".", "../../src/"
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "3.0.0 <= v < 4.0.0"
|
||||
},
|
||||
"elm-version": "0.16.0 <= v < 0.17.0"
|
||||
}
|
||||
34
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/rewind.elm
vendored
Normal file
34
intro/part7/tests/elm-stuff/packages/mgold/elm-random-pcg/5.0.2/test/rewind.elm
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
module RewindTest exposing (..)
|
||||
|
||||
{-| Demonstrates that `fastForward` may also be used to rewind. We create a seed, fastForward it, then rewind it to get
|
||||
back the original seed.
|
||||
-}
|
||||
|
||||
import Random.Pcg as Random
|
||||
import Html
|
||||
import Html.App
|
||||
|
||||
|
||||
n =
|
||||
31
|
||||
|
||||
|
||||
seed0 =
|
||||
Random.initialSeed 628318
|
||||
|
||||
|
||||
seed1 =
|
||||
Random.fastForward n seed0
|
||||
|
||||
|
||||
seed2 =
|
||||
Random.fastForward -n seed1
|
||||
|
||||
|
||||
main : Program Never
|
||||
main =
|
||||
Html.App.beginnerProgram
|
||||
{ model = ()
|
||||
, update = \_ _ -> ()
|
||||
, view = \() -> Html.text <| toString [ seed0, seed1, seed2 ]
|
||||
}
|
||||
Reference in New Issue
Block a user