diff --git a/stack--current/3-advanced--browser/NOTES.md b/stack--current/3-advanced--browser/NOTES.md index 3dbaa884..09522647 100644 --- a/stack--current/3-advanced--browser/NOTES.md +++ b/stack--current/3-advanced--browser/NOTES.md @@ -1,4 +1,17 @@ + + + + +## fonts + +Good combo used by A. to solve the "system" instability +* standard = https://rsms.me/inter/ +* mono = https://www.jetbrains.com/lp/mono/ + + + +## TOSORT Modern CSS * uses `:root` https://developer.mozilla.org/en-US/docs/Web/CSS/:root * ... @@ -24,5 +37,8 @@ TODO semantic fonts TODO font--hyperlegible https://en.wikipedia.org/wiki/Atkinson_Hyperlegible +TODO font -- monospace https://monaspace.githubnext.com/ https://fonts.google.com/specimen/Space+Mono + + TODO use @scope? https://developer.chrome.com/docs/css-ui/at-scope 2024/08 no FF diff --git a/stack--current/3-advanced--multi/rich-text-format/src/sugar/builder.ts b/stack--current/3-advanced--multi/rich-text-format/src/sugar/builder.ts index d96132ee..b76c28d8 100644 --- a/stack--current/3-advanced--multi/rich-text-format/src/sugar/builder.ts +++ b/stack--current/3-advanced--multi/rich-text-format/src/sugar/builder.ts @@ -169,6 +169,7 @@ function create($type: NodeType): Builder { return pushRawNode(kv_node, options) } + // TODO rename value() like lodash chain? function done(): CheckedNode { return $node } diff --git a/stack--current/3-advanced/ts--types--web/src/01-links/types.ts b/stack--current/3-advanced/ts--types--web/src/01-links/types.ts index 370e2857..0b729f77 100644 --- a/stack--current/3-advanced/ts--types--web/src/01-links/types.ts +++ b/stack--current/3-advanced/ts--types--web/src/01-links/types.ts @@ -70,8 +70,8 @@ type URI‿x = Uri‿str | SchemeSpecificURIPart type LinkRelation = string -/** A more generic hyperlink than HTML's - * following hypermedia theory +/** A more generic hyperlink than HTML's following hypermedia theory + * see https://hypermedia.systems/ */ interface Hyperlink extends WithLang { href: URI‿x @@ -82,6 +82,7 @@ interface Hyperlink extends WithLang { rel: LinkRelation[] // https://www.iana.org/assignments/link-relations/link-relations.xhtml cta?: string // if present, replace / complement the anchor content + // TODO label? target?: never // TODO clarify @@ -99,6 +100,8 @@ interface Hyperlink extends WithLang { // ping // referrer policy // attribution https://wicg.github.io/attribution-reporting-api/?sjid=5871821160398133867-AP#monkeypatch-attributionsrc + + // reducer action? } ///////////////////////////////////////////////// diff --git a/stack--current/5-incubator/active--no-pkg/bite-sized/lists/senior-dev/tech-bites--concepts.md b/stack--current/5-incubator/active--no-pkg/bite-sized/lists/senior-dev/tech-bites--concepts.md index b48e77fe..f92ad527 100644 --- a/stack--current/5-incubator/active--no-pkg/bite-sized/lists/senior-dev/tech-bites--concepts.md +++ b/stack--current/5-incubator/active--no-pkg/bite-sized/lists/senior-dev/tech-bites--concepts.md @@ -133,6 +133,10 @@ crunch culture -- low/high context https://journals.sagepub.com/doi/10.1177/0146167212455828 Cupertino effect = bad spell checking Cupertino effect currying https://en.wikipedia.org/wiki/Currying +data interchange format -- https://capnproto.org/ +data interchange format -- JSON -- binary https://msgpack.org/ +data interchange format -- JSON https://www.json.org/ +data interchange format -- protobuf https://github.com/protocolbuffers/protobuf databases databases -- joins https://justinjaffray.com/joins-13-ways/ databases -- normalization @@ -304,6 +308,7 @@ migrations mocha / chai monitoring = observing systems, collecting metrics, evaluating those metrics over time, and then using them to make decisions or take actions monolith = over time become poorly structured, containing many different, sometimes competing conventions. These conventions and “styles” sprawl throughout the monolith and make it difficult to understand what is going on. Because structures are built with different conventions, to work in the monolith safely, you have to examine everything to make sure you understand this instance of this pattern. It’s not safe to assume anything. This, combined with the lack of boundaries in the monolith means that every change incurs a huge cost in examination and understanding before it can be safely implemented. This skews developer performance to tenure - the longer you have been staring at the code, the more you have wrapped your head around and the faster you can go (mostly). New developers should not be worried about the time it takes to be effective in the monolith - it's the monolith’s fault, not yours." +multi tenant -- isolation MVC (Model View Controller) namespace naming https://ntietz.com/blog/when-to-use-cute-names-or-descriptive-names/ diff --git a/stack--current/5-incubator/active--no-pkg/bite-sized/lists/senior-dev/tech-bites--system.md b/stack--current/5-incubator/active--no-pkg/bite-sized/lists/senior-dev/tech-bites--system.md index 8115f51b..be4398d9 100644 --- a/stack--current/5-incubator/active--no-pkg/bite-sized/lists/senior-dev/tech-bites--system.md +++ b/stack--current/5-incubator/active--no-pkg/bite-sized/lists/senior-dev/tech-bites--system.md @@ -33,6 +33,10 @@ ACID -- 2 Consistency = integrity constraints: "valid state" before AND after a ACID -- 3 Isolation = "independent transactions" ACID -- 4 Durability = transaction resistance to system failures "once committed, always committed" ACID = a set of properties of database transactions intended to guarantee data validity despite errors, power failures, and other mishaps https://en.wikipedia.org/wiki/ACID +API -- contracts +API -- Diogo Lucas classification = far-team, near-team and inner-team. inner team = used within a team or between partner teams, near team = "Conway APIs" between teams that don't always communicate with each other, Far-team API = between teams that have low-bandwidth communications +API -- hybrids = reconcile the need for a stable public API that will not constantly disrupt your carefully tended ecosystem with your team’s ability to move fast and (eventually) break stuff? cater for different requirements regarding security and SLAs or to radically different client natures? https://www.youtube.com/watch?v=eqy609JleoE +API -- visibility = public/external > internal > team > private beta. Guidelines: Consider a public-by-default approach, even if you are starting at a lower level of access (helps dogfooding, new use cases. Treat your internal APIs as candidates for Public level access (bc happens quickly, sometimes for merging with a public one) API gateway API-First = Built with APIs from the ground up. All functionality is exposed through an API app -- a11y @@ -332,6 +336,9 @@ organizations PACELC theorem = extension of CAP https://en.wikipedia.org/wiki/PACELC_theorem peak hours, off-peak hours performance +periods -- deprecation notice +periods -- maintenance +periods -- warranty permissions Personal data service (PDS) = user's central point of control for their personal information https://en.wikipedia.org/wiki/Personal_data_service perspective -- non-tech -- business = creates business model that integrates IT strategy diff --git a/stack--current/A-apps--core/the-boring-rpg/state/src/reducers/base.ts b/stack--current/A-apps--core/the-boring-rpg/state/src/reducers/base.ts index a54ef914..2fc7a6fd 100644 --- a/stack--current/A-apps--core/the-boring-rpg/state/src/reducers/base.ts +++ b/stack--current/A-apps--core/the-boring-rpg/state/src/reducers/base.ts @@ -53,6 +53,7 @@ function on_start_session(previous_state: Immutable, is_web_diversity_sup } // TODO recap here as Engagement flow? + // NO because would cause a non-user initiated mutation, which would trigger a useless sync // new achievements may have appeared // (new content = not the same as a migration) diff --git a/stack--current/A-apps--core/the-boring-rpg/xx-sandbox/src/hateoas/index.ts b/stack--current/A-apps--core/the-boring-rpg/xx-sandbox/src/hateoas/index.ts index 2e4d5d82..383c9f72 100644 --- a/stack--current/A-apps--core/the-boring-rpg/xx-sandbox/src/hateoas/index.ts +++ b/stack--current/A-apps--core/the-boring-rpg/xx-sandbox/src/hateoas/index.ts @@ -3,7 +3,6 @@ import { type Hyperlink } from '@offirmo-private/ts-types-web' import * as RichText from '@offirmo-private/rich-text-format' import * as State from '@tbrpg/state' -import * as RRT from '@tbrpg/ui--rich-text' import { prettifyꓽjson } from '../services/misc.js' @@ -17,7 +16,7 @@ import { type StepIteratorYieldResult, type StepIteratorReturnResult, } from '@offirmo-private/view--chat' -import to_terminal from '@offirmo-private/rich-text-format--to-terminal' +import { create_action, type ActionPlay } from '@tbrpg/interfaces' ///////////////////////////////////////////////// // TODO async to pretend we're talking to a server (even if it's a worker) @@ -41,18 +40,63 @@ class Game { ///////////////////////////////////////////////// -function HATEOASᐧGET(state: Immutable, link: Hyperlink['href'] = ''): RichText.Document { - console.log(`HATEOASᐧGET("${link}")`) +function HATEOASᐧGET(state: Immutable, url: Hyperlink['href'] = ''): RichText.Document { + console.log(`↘ HATEOASᐧGET("${url}")`) -// const $doc = State.getꓽrecap(state.u_state) // TODO clarify recap/mode + // TODO URL normalization (one day) + let $builder = RichText.fragmentⵧblock() - switch (link) { - case '': - return State.getꓽrecap(state.u_state) + /*.pushNode(RichText.heading().pushText('Identity:').done(), {id: 'header'}) + .pushNode( + RichText.listⵧunordered() + .pushKeyValue('name', $doc_name) + .pushKeyValue('class', $doc_class) + .done() + ) + .done()*/ + + switch (url) { + case '': { // home + $builder = $builder.pushHeading('Currently adventuring…') + + // NO recap of last adventure, it's a different route? + // TODO clarify + + if (State.is_inventory_full(state.u_state)) { + $builder = $builder.pushNode( + RichText.strong().pushText('Your inventory is full!').done(), + ) + } + + if(State.getꓽavailable_energy‿float(state.t_state) >= 1) { + $builder = $builder.pushBlockFragment('You can play now!') + } + else { + $builder = $builder.pushBlockFragment('You can play again in ' + State.getꓽhuman_time_to_next_energy(state)) + } + + // actions! + // 1. we're home so links to other "modes/mechanics" + const modeⵧequipment: Hyperlink = { + href: '/equipment', + cta: 'Manage equipment', + } + $builder = $builder.addHints({ + + }) + // 2. links related to the current mode + const actionⵧplay = create_action() + + break + } + + case '/adventure': // ?? default: - throw new Error(`Unknown resource "${link}"!`) + throw new Error(`Unknown resource locator "${url}"!`) } + + return $builder.done() } ///////////////////////////////////////////////// @@ -61,8 +105,10 @@ type ContentType = string | RichText.Document class GameChat implements StepIterator { game: Game = new Game() + status: 'starting' | 'normal' = 'starting' is_done: boolean = false - hypermedia: any = undefined + current_route = '' + non_interactive_steps_count = 0 constructor() { this.game.on_start_session() @@ -76,8 +122,15 @@ class GameChat implements StepIterator { } satisfies StepIteratorReturnResult } + const value = this.gen_next_step(p) + this.non_interactive_steps_count++ + if (this.non_interactive_steps_count >= 5) { + console.error('SCHEDULING EXIT because too many non-interactive steps!') + this.is_done = true + } + return { - value: this.gen_next_step(p), + value, done: false, } satisfies StepIteratorYieldResult } @@ -85,6 +138,17 @@ class GameChat implements StepIterator { gen_next_step({ last_step, last_answer }: StepIteratorTNext): Step { const state = this.game.getꓽstate() + if (this.status === 'starting') { + this.status = 'normal' + // skip the "between actions" messages + const $doc = State.getꓽrecap(state.u_state) // TODO clarify recap/mode + const step: Step = { + type: StepType.simple_message, + msg: $doc, + } + return step + } + const pef = State.getꓽoldest_pending_engagementⵧflow(state.u_state) if (pef) { //console.log('[PEF]', to_terminal(pef.$doc)) @@ -100,21 +164,27 @@ class GameChat implements StepIterator { const penf = State.getꓽoldest_pending_engagementⵧnon_flow(state.u_state) if (penf) { - //console.log('[PENF]', to_terminal(penf.$doc)) - const step: Step = { - type: StepType.simple_message, - msg: penf.$doc, - callback: () => { - this.game.state = State.acknowledge_engagement_msg_seen(this.game.state, penf.uid) + //console.log('[PENF]', to_terminal(penf.$doc)) + const step: Step = { + type: StepType.simple_message, + msg: penf.$doc, + callback: () => { + this.game.state = State.acknowledge_engagement_msg_seen(this.game.state, penf.uid) + } } + return step } - return step + + const hypermedia = HATEOASᐧGET(state, this.current_route) + + const step: Step = { + type: StepType.simple_message, + msg: hypermedia, } - this.is_done = true + + // TODO extract actions! /* - console.log('/////////////////////////////////////////////////') - // TODO should be part of recap? if (State.is_inventory_full(state.u_state)) { console.warn('[special message] Inventory is full!') } @@ -122,6 +192,8 @@ class GameChat implements StepIterator { console.log('[special message] You can play now!') } + + console.log('/////////////////////////////////////////////////') console.log('Actions:', RichText.renderⵧto_actions($doc)) */ @@ -134,14 +206,6 @@ class GameChat implements StepIterator { //console.log(to_terminal($doc)) */ - - const hypermedia = HATEOASᐧGET(state) - - const step: Step = { - type: StepType.simple_message, - msg: hypermedia, - } - return step }