Compare commits
20 Commits
v0.40.1
...
3f5e4f4290
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f5e4f4290 | |||
| 0797e9a993 | |||
| c53b42342b | |||
| 123aa6d099 | |||
| 331d932c4b | |||
| 716e5f04cf | |||
| ef9d914b99 | |||
| 005efa2ee4 | |||
| 1190ed3ce6 | |||
| 2869e1c34e | |||
| 783f01628e | |||
| 94a6feb5db | |||
| 3daaf47689 | |||
| c00656ec8f | |||
| aea2167eee | |||
| 0ed91ea24c | |||
| 18af49c0f3 | |||
| e208245036 | |||
| 0247efcb07 | |||
| 1d5266a811 |
@@ -109,6 +109,18 @@ Owns:
|
||||
- Achievement unlock condition evaluation
|
||||
- Seeded RNG for reproducible deals
|
||||
|
||||
**Rules decisions:**
|
||||
- **Stock recycling is unlimited in every draw mode — by design.** Extra
|
||||
passes through the stock are discouraged via the upstream score penalty
|
||||
(applied by the `card_game`/`klondike` session), never blocked with a
|
||||
`MoveError`. This matches mainstream digital solitaire (unlimited redeals
|
||||
in Draw-1) rather than strict tournament rules (3-pass cap). It is load-
|
||||
bearing: the difficulty seed catalog and the winnable-deal solver are
|
||||
verified under unlimited recycling, so introducing a hard pass limit would
|
||||
invalidate both. Locked in by the
|
||||
`draw_one_recycling_is_unlimited_by_design` test in
|
||||
`solitaire_core/src/game_state.rs`. (Decision record: Gitea issue #117.)
|
||||
|
||||
### `solitaire_sync`
|
||||
**Dependencies:** `serde`, `serde_json`, `uuid`, `chrono` only.
|
||||
|
||||
|
||||
@@ -8,6 +8,12 @@ project follows [Semantic Versioning](https://semver.org/).
|
||||
|
||||
### Added
|
||||
|
||||
- **Rules decision record: unlimited stock recycling.** Documented in
|
||||
`ARCHITECTURE.md` that unlimited recycling with score penalties (matching
|
||||
mainstream digital solitaire) is intentional, and locked it in with a core
|
||||
test — the difficulty seed catalog and winnable-deal solver are verified
|
||||
under this rule. Resolves the last open finding from the June 500-game
|
||||
audit (issue #117).
|
||||
- **Analytics validation runbook.** Documented native Matomo live validation,
|
||||
expected event payloads, and the current web/WASM analytics split.
|
||||
- **Android smoke-test runbook.** Updated the Android doc with the current
|
||||
@@ -37,6 +43,18 @@ project follows [Semantic Versioning](https://semver.org/).
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Tableau fill on foldables / tall screens.** The tableau fan now spreads from
|
||||
each column's total depth (face-down cards included) and refills on the
|
||||
cold-start deal, every move, and on resize (incl. the Android safe-area-inset
|
||||
resize and fold/unfold), so a near-square viewport such as an unfolded Galaxy
|
||||
Fold no longer leaves the bottom of the screen empty. The fan spread cap was
|
||||
raised so very tall / narrow viewports (e.g. a foldable cover screen) fill
|
||||
further.
|
||||
- **Card-move animation jank.** A move now rebuilds a card's child visuals only
|
||||
when its appearance changes (flip / resize / accessibility) instead of
|
||||
despawning and respawning every card's children each `StateChangedEvent`,
|
||||
removing the per-move spike that stuttered the slide animation on
|
||||
high-resolution devices.
|
||||
- **Android and modal safe-area layout.** Modal cards now center within the
|
||||
usable area between status and gesture bars, additional modal-spawn guards were
|
||||
added, and Android build scripts now auto-discover SDK/NDK paths and strip
|
||||
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env bash
|
||||
# Live-watch the Gitea Actions deploy pipeline for Ferrous Solitaire.
|
||||
#
|
||||
# Polls recent workflow runs and prints a compact status block each cycle.
|
||||
# Stops when the newest docker-build (the deploy) has completed and no
|
||||
# web-wasm-rebuild is still pending — i.e. the full fix is live.
|
||||
#
|
||||
# Usage: ./scripts/watch_deploy.sh [interval_seconds]
|
||||
# token is read from ~/.config/tea/config.yml (never printed).
|
||||
set -uo pipefail
|
||||
|
||||
REPO="funman300/Ferrous-Solitaire"
|
||||
BASE="https://git.aleshym.co/api/v1/repos/${REPO}"
|
||||
INTERVAL="${1:-20}"
|
||||
CFG="${HOME}/.config/tea/config.yml"
|
||||
|
||||
TOKEN="$(grep -E '^[[:space:]]*token:' "$CFG" | head -1 | sed -E 's/.*token:[[:space:]]*//' | tr -d '"'\'' ')"
|
||||
[ -z "$TOKEN" ] && { echo "error: no token in $CFG" >&2; exit 1; }
|
||||
|
||||
echo "── watching ${REPO} deploy (poll ${INTERVAL}s, Ctrl-C to stop) ──"
|
||||
|
||||
while :; do
|
||||
json="$(curl -s --max-time 20 -H "Authorization: token ${TOKEN}" "${BASE}/actions/runs?limit=6")"
|
||||
# Print rows + emit the deploy state on the last line (parsed below).
|
||||
# JSON is passed via env var because `python3 -` reads its program from the
|
||||
# heredoc on stdin, so stdin can't also carry the data.
|
||||
out="$(JSON_DATA="$json" python3 - <<'PY'
|
||||
import os, sys, json, datetime
|
||||
now = datetime.datetime.now().strftime("%H:%M:%S")
|
||||
raw = os.environ.get("JSON_DATA", "").strip()
|
||||
try:
|
||||
d = json.loads(raw)
|
||||
except Exception:
|
||||
print("[%s] (api unavailable, retrying)" % now)
|
||||
print("STATE=DEPLOYING")
|
||||
sys.exit(0)
|
||||
runs = d.get("workflow_runs", [])[:6]
|
||||
icons = {("completed","success"):"OK ", ("completed","failure"):"FAIL",
|
||||
("completed","cancelled"):"CXL "}
|
||||
def ic(s, c):
|
||||
if s == "queued": return "queue"
|
||||
if s == "in_progress": return "run.."
|
||||
return icons.get((s, c), s or "?")
|
||||
print("[%s]" % datetime.datetime.now().strftime("%H:%M:%S"))
|
||||
for r in runs:
|
||||
wf = str(r.get("path","")).split("@")[0].split("/")[-1].replace(".yml","")
|
||||
print(" %-5s %-5s %-7s %-18s %s/%s" % (
|
||||
ic(r.get("status"), r.get("conclusion")),
|
||||
r.get("id"), str(r.get("head_sha"))[:7], wf[:18],
|
||||
r.get("status"), r.get("conclusion")))
|
||||
db = [r for r in runs if "docker-build" in str(r.get("path"))]
|
||||
wr_pending = any(r.get("status") != "completed" for r in runs if "web-wasm-rebuild" in str(r.get("path")))
|
||||
top = db[0] if db else None
|
||||
live = bool(top and top.get("status")=="completed" and top.get("conclusion")=="success" and not wr_pending)
|
||||
print("STATE=%s" % ("LIVE" if live else ("WAIT_WASM" if wr_pending else "DEPLOYING")))
|
||||
PY
|
||||
)"
|
||||
echo "$out" | grep -v '^STATE='
|
||||
if echo "$out" | grep -q '^STATE=LIVE'; then
|
||||
echo ""
|
||||
echo "DEPLOY LIVE — newest docker-build succeeded, no wasm rebuild pending."
|
||||
echo " Test: https://klondike.aleshym.co/play?v=${RANDOM}"
|
||||
break
|
||||
fi
|
||||
sleep "$INTERVAL"
|
||||
done
|
||||
@@ -863,6 +863,13 @@ impl GameState {
|
||||
}
|
||||
|
||||
/// Draw cards from stock to waste. When stock is empty, recycles waste back to stock.
|
||||
///
|
||||
/// Recycling is deliberately unlimited in every draw mode: extra passes
|
||||
/// are discouraged through the upstream score penalty, never rejected
|
||||
/// with a [`MoveError`]. The difficulty seed catalog and the
|
||||
/// winnable-deal solver are verified under this rule — see the
|
||||
/// "Rules decisions" note in `ARCHITECTURE.md` (`solitaire_core`
|
||||
/// section) before considering a hard pass limit.
|
||||
pub fn draw(&mut self) -> Result<(), MoveError> {
|
||||
if self.is_won() {
|
||||
return Err(MoveError::GameAlreadyWon);
|
||||
@@ -1222,6 +1229,30 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draw_one_recycling_is_unlimited_by_design() {
|
||||
// Rules decision (Gitea #117): stock recycling is unlimited in every
|
||||
// draw mode. Extra passes are discouraged via the upstream score
|
||||
// penalty, never blocked with a MoveError. The difficulty seed
|
||||
// catalog and the winnable-deal solver are verified under this rule,
|
||||
// so a hard pass limit must not be introduced casually — see the
|
||||
// "Rules decisions" note in ARCHITECTURE.md (`solitaire_core`).
|
||||
let mut game = game_at_first_recycle().expect("could not reach recycle");
|
||||
// ~24 draws per Draw-1 pass; 2_000 draws is ample budget for 10 passes.
|
||||
for _ in 0..2_000 {
|
||||
if game.recycle_count() >= 10 {
|
||||
break;
|
||||
}
|
||||
game.draw()
|
||||
.expect("unlimited recycling: draw must never fail on pass count");
|
||||
}
|
||||
assert!(
|
||||
game.recycle_count() >= 10,
|
||||
"expected at least 10 recycles within the draw budget, got {}",
|
||||
game.recycle_count(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn undo_applies_minus_15_penalty_via_upstream_score() {
|
||||
// A foundation move scores +10 upstream; undoing it nets the move score
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ use std::collections::HashMap;
|
||||
|
||||
use bevy::math::Vec2;
|
||||
use bevy::prelude::{Resource, SystemSet};
|
||||
use solitaire_core::game_state::GameState;
|
||||
use solitaire_core::{Foundation, KlondikePile, Tableau};
|
||||
|
||||
/// Schedule labels for layout-related systems so cross-plugin ordering is
|
||||
@@ -91,6 +92,15 @@ const TABLEAU_FACEDOWN_FAN_FRAC: f32 = 0.14;
|
||||
/// this column inside the visible window.
|
||||
const MAX_TABLEAU_CARDS: f32 = 13.0;
|
||||
|
||||
/// Upper bound for the dynamic tableau fan step (fraction of card height) chosen
|
||||
/// by [`apply_dynamic_tableau_fan`]. The fan is spread to fill the available
|
||||
/// height, but a near-empty column has tiny demand, so without a cap its few
|
||||
/// cards would fling far apart on a tall viewport. At 0.6 the face-up cards keep
|
||||
/// clear overlap (a readable stack) while still filling most of a near-square /
|
||||
/// unfolded-foldable screen. Tunable purely for feel — no effect on correctness
|
||||
/// or hit-testing.
|
||||
pub(crate) const MAX_DYNAMIC_FAN_FRAC: f32 = 0.9;
|
||||
|
||||
/// Vertical pixel band reserved at the top of the play area for the HUD
|
||||
/// (action buttons, Score / Moves / Timer readouts). The card grid starts
|
||||
/// below this band so the HUD doesn't bleed into the play surface.
|
||||
@@ -275,13 +285,12 @@ pub fn compute_layout(
|
||||
);
|
||||
}
|
||||
|
||||
// Adaptive tableau fan fraction. On height-limited (desktop) windows the
|
||||
// height-based sizing already ensures a worst-case 13-card column fits at
|
||||
// TABLEAU_FAN_FRAC (0.25), so the formula returns ≈0.25 and the clamp
|
||||
// keeps it there — no change from prior behaviour. On width-limited
|
||||
// (portrait phone) windows card_size is small and lots of vertical space
|
||||
// is unused; we solve for the fraction that exactly fills the available
|
||||
// space to the bottom margin.
|
||||
// Adaptive tableau fan fraction. On height-limited windows the height-based
|
||||
// sizing already ensures a worst-case 13-card column fits at TABLEAU_FAN_FRAC,
|
||||
// so the formula returns the minimum and the clamp keeps it there. On
|
||||
// width-limited (portrait phone) windows card_size is small and lots of
|
||||
// vertical space is unused; solve for the fraction that fills the available
|
||||
// space. `apply_dynamic_tableau_fan` later refines this for the actual deal.
|
||||
//
|
||||
// avail = distance from the top of the first tableau card to the bottom
|
||||
// margin — i.e. the space available for 12 fan steps.
|
||||
@@ -292,20 +301,87 @@ pub fn compute_layout(
|
||||
} else {
|
||||
TABLEAU_FAN_FRAC
|
||||
};
|
||||
// Never go below the desktop minimum — avoids shrinking the fan on
|
||||
// degenerate near-square windows where the formula might undershoot.
|
||||
let tableau_fan_frac = ideal_fan_frac.max(TABLEAU_FAN_FRAC);
|
||||
// Scale the face-down fraction proportionally so rendering and hit-testing
|
||||
// stay in sync (TABLEAU_FACEDOWN_FAN_FRAC / TABLEAU_FAN_FRAC = 0.48 ratio).
|
||||
let facedown_scale = TABLEAU_FACEDOWN_FAN_FRAC / TABLEAU_FAN_FRAC;
|
||||
let tableau_facedown_fan_frac = tableau_fan_frac * facedown_scale;
|
||||
let available_tableau_height = avail;
|
||||
|
||||
Layout {
|
||||
card_size,
|
||||
pile_positions,
|
||||
tableau_fan_frac,
|
||||
tableau_facedown_fan_frac,
|
||||
available_tableau_height: avail,
|
||||
available_tableau_height,
|
||||
}
|
||||
}
|
||||
|
||||
/// Spread the tableau fan so the deepest column fills the available vertical
|
||||
/// height for the *current* deal, mutating `layout.tableau_fan_frac` and its
|
||||
/// face-down companion in place.
|
||||
///
|
||||
/// `compute_layout` is pure geometry and sizes the fan for a worst-case 13-card
|
||||
/// column, so early in a game (shallow columns) a tall or near-square viewport
|
||||
/// — e.g. an unfolded foldable — is left with a large empty band below the
|
||||
/// tableau. This refines the fan once the actual deal is known.
|
||||
///
|
||||
/// Depth is measured across *all* cards in a column, each face-down card
|
||||
/// weighted by the fixed face-down/face-up step ratio. Counting the face-down
|
||||
/// portion (not just the face-up tail) is what fills the lower screen on a fresh
|
||||
/// deal, where the deepest column is several face-down cards under one face-up
|
||||
/// one. Deeper columns drive the fraction down so everything still fits;
|
||||
/// [`TABLEAU_FAN_FRAC`] floors it and [`MAX_DYNAMIC_FAN_FRAC`] caps it.
|
||||
///
|
||||
/// Called from card-sync at startup and on every `StateChangedEvent`, and from
|
||||
/// the resize pipeline after `compute_layout`, so the cold-start deal, ongoing
|
||||
/// play, and fold/unfold all stay filled. `card_position` / `card_positions`
|
||||
/// read the same fractions, so rendering and hit-testing remain in sync.
|
||||
pub(crate) fn apply_dynamic_tableau_fan(game: &GameState, layout: &mut Layout) {
|
||||
let card_h = layout.card_size.y;
|
||||
let avail = layout.available_tableau_height;
|
||||
if card_h <= 0.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let facedown_ratio = TABLEAU_FACEDOWN_FAN_FRAC / TABLEAU_FAN_FRAC;
|
||||
|
||||
// "Step demand" of a column: the vertical offset of its bottom card from its
|
||||
// top card, in units of the face-up fan step. Every card except the last
|
||||
// contributes one step, weighted down to `facedown_ratio` while face-down.
|
||||
let max_demand = [
|
||||
Tableau::Tableau1,
|
||||
Tableau::Tableau2,
|
||||
Tableau::Tableau3,
|
||||
Tableau::Tableau4,
|
||||
Tableau::Tableau5,
|
||||
Tableau::Tableau6,
|
||||
Tableau::Tableau7,
|
||||
]
|
||||
.into_iter()
|
||||
.map(|tableau| {
|
||||
let pile = game.pile(KlondikePile::Tableau(tableau));
|
||||
let steps = pile.len().saturating_sub(1);
|
||||
pile.iter()
|
||||
.take(steps)
|
||||
.map(|(_, face_up)| if *face_up { 1.0 } else { facedown_ratio })
|
||||
.sum::<f32>()
|
||||
})
|
||||
.fold(0.0_f32, f32::max);
|
||||
|
||||
// No fannable column (every tableau pile has ≤ 1 card) — leave the fractions
|
||||
// at the values compute_layout set.
|
||||
if max_demand <= 0.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let ideal = avail / (max_demand * card_h);
|
||||
let new_frac = ideal.clamp(TABLEAU_FAN_FRAC, MAX_DYNAMIC_FAN_FRAC);
|
||||
let new_facedown_frac = new_frac * facedown_ratio;
|
||||
|
||||
if (layout.tableau_fan_frac - new_frac).abs() > 1e-4 {
|
||||
layout.tableau_fan_frac = new_frac;
|
||||
}
|
||||
if (layout.tableau_facedown_fan_frac - new_facedown_frac).abs() > 1e-4 {
|
||||
layout.tableau_facedown_fan_frac = new_facedown_frac;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -191,10 +191,12 @@ fn apply_safe_area_to_modal_scrims(
|
||||
/// whatever `SafeAreaInsets` are current at that moment.
|
||||
///
|
||||
/// On Android the `android::rearm_on_resumed` system runs in the same frame
|
||||
/// and resets both `SafeAreaPollTries` and `SafeAreaInsets` to zero, causing
|
||||
/// `refresh_insets` to re-poll JNI over the next few frames. When it resolves
|
||||
/// the correct values, `on_safe_area_changed` in `table_plugin` emits a second
|
||||
/// synthetic `WindowResized` and the layout converges to the right position.
|
||||
/// and resets `SafeAreaPollTries` (the cached `SafeAreaInsets` keep their
|
||||
/// last-known values), causing `refresh_insets` to re-poll JNI over the next
|
||||
/// few frames. If the insets changed while backgrounded, `on_safe_area_changed`
|
||||
/// in `table_plugin` emits a second synthetic `WindowResized` and the layout
|
||||
/// converges to the right position; if they didn't, nothing is rewritten and
|
||||
/// the layout stays put.
|
||||
///
|
||||
/// On non-Android targets this handler still fires — it ensures that a resume
|
||||
/// event always refreshes the layout (e.g., after a minimise/restore on
|
||||
@@ -232,9 +234,14 @@ mod android {
|
||||
pub(super) struct SafeAreaPollTries(pub u32);
|
||||
|
||||
/// Polls Android for safe-area insets until we get a non-zero
|
||||
/// reading, then stops. `getRootWindowInsets()` returns `null` (or
|
||||
/// all-zero `Insets`) until the decor view has been laid out, which
|
||||
/// is typically frame 1–3 of a fresh launch.
|
||||
/// reading, then settles until [`rearm_on_resumed`] re-arms it on the
|
||||
/// next foreground resume — insets can change while backgrounded
|
||||
/// (rotation, fold/unfold, gesture ↔ 3-button nav). The poll counter
|
||||
/// (not `insets.is_populated()`) gates the loop, so a re-armed cycle
|
||||
/// re-queries JNI even though cached values are already populated.
|
||||
/// `getRootWindowInsets()` returns `null` (or all-zero `Insets`)
|
||||
/// until the decor view has been laid out, which is typically frame
|
||||
/// 1–3 of a fresh launch.
|
||||
pub(super) fn refresh_insets(
|
||||
mut insets: ResMut<SafeAreaInsets>,
|
||||
mut poll: ResMut<SafeAreaPollTries>,
|
||||
@@ -243,18 +250,25 @@ mod android {
|
||||
// devices that genuinely report zero insets.
|
||||
const MAX_TRIES: u32 = 120; // ~2 seconds @ 60 fps
|
||||
|
||||
if poll.0 >= MAX_TRIES || insets.is_populated() {
|
||||
if poll.0 >= MAX_TRIES {
|
||||
return;
|
||||
}
|
||||
poll.0 += 1;
|
||||
|
||||
match query_insets() {
|
||||
Ok(v) if v.is_populated() => {
|
||||
info!(
|
||||
"safe_area: insets resolved top={} bottom={} left={} right={} (after {} frames)",
|
||||
v.top, v.bottom, v.left, v.right, poll.0
|
||||
);
|
||||
*insets = v;
|
||||
if *insets != v {
|
||||
info!(
|
||||
"safe_area: insets resolved top={} bottom={} left={} right={} (after {} frames)",
|
||||
v.top, v.bottom, v.left, v.right, poll.0
|
||||
);
|
||||
*insets = v;
|
||||
}
|
||||
// Settled for this poll cycle; `rearm_on_resumed` re-arms on
|
||||
// the next resume. Writing `insets` only on an actual change
|
||||
// keeps resource change detection (and the relayout it
|
||||
// triggers) quiet on resumes where nothing moved.
|
||||
poll.0 = MAX_TRIES;
|
||||
}
|
||||
Ok(_) => {
|
||||
// Layout not ready yet; try again next frame.
|
||||
|
||||
@@ -11,7 +11,9 @@ use solitaire_core::Suit;
|
||||
|
||||
use crate::events::{HintVisualEvent, StateChangedEvent};
|
||||
use crate::hud_plugin::HudVisibility;
|
||||
use crate::layout::{Layout, LayoutResource, LayoutSystem, TABLE_COLOUR, compute_layout};
|
||||
use crate::layout::{
|
||||
Layout, LayoutResource, LayoutSystem, TABLE_COLOUR, apply_dynamic_tableau_fan, compute_layout,
|
||||
};
|
||||
use crate::resources::GameStateResource;
|
||||
use crate::safe_area::SafeAreaInsets;
|
||||
use crate::settings_plugin::{SettingsChangedEvent, SettingsResource};
|
||||
@@ -348,12 +350,13 @@ fn spawn_pile_markers(commands: &mut Commands, layout: &Layout) {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[allow(clippy::type_complexity, clippy::too_many_arguments)]
|
||||
fn on_window_resized(
|
||||
mut events: MessageReader<WindowResized>,
|
||||
safe_area: Option<Res<SafeAreaInsets>>,
|
||||
windows: Query<&Window>,
|
||||
hud_vis: Option<Res<HudVisibility>>,
|
||||
game: Option<Res<GameStateResource>>,
|
||||
mut layout_res: Option<ResMut<LayoutResource>>,
|
||||
mut backgrounds: Query<
|
||||
(&mut Sprite, &mut Transform),
|
||||
@@ -370,7 +373,16 @@ fn on_window_resized(
|
||||
let safe_area_top = insets.top / scale;
|
||||
let safe_area_bottom = insets.bottom / scale;
|
||||
let hud_visible = hud_vis.as_deref().copied().unwrap_or_default() == HudVisibility::Visible;
|
||||
let new_layout = compute_layout(window_size, safe_area_top, safe_area_bottom, hud_visible);
|
||||
let mut new_layout = compute_layout(window_size, safe_area_top, safe_area_bottom, hud_visible);
|
||||
|
||||
// compute_layout sizes the fan for a worst-case column; refine it to the
|
||||
// current deal so a resize (incl. the Android safe-area-inset resize that
|
||||
// fires in the first few frames, and fold/unfold on foldables) keeps the
|
||||
// tableau filling the viewport instead of snapping back to the sparse
|
||||
// worst-case fan.
|
||||
if let Some(game) = game.as_ref() {
|
||||
apply_dynamic_tableau_fan(&game.0, &mut new_layout);
|
||||
}
|
||||
|
||||
if let Some(layout_res) = layout_res.as_deref_mut() {
|
||||
layout_res.0 = new_layout.clone();
|
||||
|
||||
@@ -1649,63 +1649,63 @@ function __wbg_get_imports() {
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 114855, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hea4b5125da4e5ded);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 114857, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hfb2e9a2f0bbd9ecc);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000002: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000003: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array<any>"), NamedExternref("ResizeObserver")], shim_idx: 9847, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h0fec466277fb30e8);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array<any>"), NamedExternref("ResizeObserver")], shim_idx: 9843, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h876550298b312ff8);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000004: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array<any>")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_3);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Array<any>")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_3);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000005: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_4);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_4);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000006: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("FocusEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_5);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("FocusEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_5);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000007: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_6);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_6);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000008: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PageTransitionEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_7);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PageTransitionEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_7);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000009: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PointerEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_8);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("PointerEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_8);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_000000000000000a: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("WheelEvent")], shim_idx: 9841, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_9);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("WheelEvent")], shim_idx: 9830, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_9);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_000000000000000b: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Option(NamedExternref("Blob"))], shim_idx: 9843, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hf05069bc44820cc5);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Option(NamedExternref("Blob"))], shim_idx: 9840, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h657f46feffff6fe4);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_000000000000000c: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 9839, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h5e26b448f43bfba9);
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 9834, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h545edb23183e448a);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_000000000000000d: function(arg0) {
|
||||
@@ -1769,55 +1769,55 @@ function __wbg_get_imports() {
|
||||
};
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h5e26b448f43bfba9(arg0, arg1) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h5e26b448f43bfba9(arg0, arg1);
|
||||
function wasm_bindgen__convert__closures_____invoke__h545edb23183e448a(arg0, arg1) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h545edb23183e448a(arg0, arg1);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_3(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_3(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_3(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_3(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_4(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_4(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_4(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_4(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_5(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_5(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_5(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_5(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_6(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_6(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_6(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_6(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_7(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_7(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_7(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_7(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_8(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_8(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_8(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_8(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_9(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h2a0b90ad2a013a3e_9(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_9(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h15aa57dbc666225a_9(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__hea4b5125da4e5ded(arg0, arg1, arg2) {
|
||||
const ret = wasm.wasm_bindgen__convert__closures_____invoke__hea4b5125da4e5ded(arg0, arg1, arg2);
|
||||
function wasm_bindgen__convert__closures_____invoke__hfb2e9a2f0bbd9ecc(arg0, arg1, arg2) {
|
||||
const ret = wasm.wasm_bindgen__convert__closures_____invoke__hfb2e9a2f0bbd9ecc(arg0, arg1, arg2);
|
||||
if (ret[1]) {
|
||||
throw takeFromExternrefTable0(ret[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__h0fec466277fb30e8(arg0, arg1, arg2, arg3) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h0fec466277fb30e8(arg0, arg1, arg2, arg3);
|
||||
function wasm_bindgen__convert__closures_____invoke__h876550298b312ff8(arg0, arg1, arg2, arg3) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h876550298b312ff8(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
function wasm_bindgen__convert__closures_____invoke__hf05069bc44820cc5(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__hf05069bc44820cc5(arg0, arg1, isLikeNone(arg2) ? 0 : addToExternrefTable0(arg2));
|
||||
function wasm_bindgen__convert__closures_____invoke__h657f46feffff6fe4(arg0, arg1, arg2) {
|
||||
wasm.wasm_bindgen__convert__closures_____invoke__h657f46feffff6fe4(arg0, arg1, isLikeNone(arg2) ? 0 : addToExternrefTable0(arg2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user