Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

weather.gno

2.63 Kb · 70 lines
 1package golf
 2
 3import (
 4	"strconv"
 5	"time"
 6
 7	"gno.land/p/nym-alexiscolin000/gnogolf/course"
 8	"gno.land/p/nt/ufmt/v0"
 9)
10
11// The weather changes every five minutes of chain time, differs from hole to
12// hole and is the same for everyone (course.ForecastFor hashes hole and
13// period). A round is played in the weather of the period it started in, and
14// records it, so anyone can replay it.
15
16// PeriodSeconds is how long one weather lasts.
17const PeriodSeconds = 5 * 60
18
19// Period is the weather period of the chain's current block time.
20func Period() int64 { return time.Now().Unix() / PeriodSeconds }
21
22// weatherOf is the hole's weather in a period: seeded by its id, so each
23// version of a slot has weather of its own.
24func weatherOf(e *entry, h *course.Simple, period int64) course.Forecast {
25	return course.ForecastFor(e.id, e.world, h, period)
26}
27
28// forecastJSON is a forecast as an object, head its first fields if any
29// (as `"version":1,`). Zones' air and capped are not printed: only the wind
30// has them, always.
31func forecastJSON(head string, f course.Forecast) string {
32	return "{" + head + `"period":` + strconv.FormatInt(f.Period, 10) + `,"kind":` + jstr(f.Kind) +
33		`,"wind":` + jvec(f.Wind) + `,"zones":` + zonesJSON(f.Zones, false) + "}"
34}
35
36// Weather is a hole's weather in a period, as JSON: the zones a client draws
37// and the chain plays under. Its "gas" is what a commit there spends before
38// its first shot (decoding and forecast), counted against the commit's
39// budget: a client adds it to its shots' estimate. A future period panics.
40func Weather(hole string, period int64) string {
41	notAhead(period)
42	e := readHole(hole)
43	fc := weatherOf(e, e.hole(), period)
44	return forecastJSON(versionJSON+`,"gas":`+strconv.FormatInt(fixedGas(e, fc), 10)+",", fc)
45}
46
47// notAhead refuses a period still to come. It is no secret (ForecastFor is
48// pure): this only keeps reads to the weather a round can be played in.
49func notAhead(period int64) {
50	if period > Period() {
51		panic("golf: that weather has not come yet")
52	}
53}
54
55// notOver refuses a round's weather two periods or more behind: a round left
56// for later cannot be finished days on in the weather it picked.
57func notOver(period int64) {
58	if period < Period()-1 {
59		panic(ufmt.Sprintf("golf: this round's weather (period %d) is over: Reset to play again", period))
60	}
61}
62
63// playablePeriod checks the period a round starts under: the current one, or
64// the one just gone, for a round that ran over the turn of the period.
65func playablePeriod(period int64) {
66	now := Period()
67	if period != now && period != now-1 {
68		panic(ufmt.Sprintf("golf: period %d is not the current weather (%d) or the one before", period, now))
69	}
70}