text:
# nScheme

## Test the bootstrap interpreter

`raco test *.rkt`

## Bootstrap the compiler and evaluator

Run `./clean-bootstrap`, or manually run:

```
racket bootstrap.rkt
raco exe -o compile compile.scm.rkt
./compile eval.scm
raco exe -o eval eval.scm.rkt
./eval -e "(printf '\"hello ~a\n\" 'world)"
```

## TODO
* store near-source language ASTs as virtualized programs
  * usual ASTs, but everything allocated in a VM heap
    * heap values are values annotated with a virtual address
      * no lookup needed in most cases (value is local)
      * address is useful for comparison, sharing, gc, serialization, modelling mutable state
    * ASTs themselves, and any values they embed (e.g., in ast:quote), are heap values
  * still CPS-convert if supporting delimited continuations and dynamic parameters
  * optionally optimize ASTs without changing representation
    * e.g., some variant of partial evaluation
  * implement resource-budgeted evaluation
    * optionally w/ provenance tracking for debugging
    * interrupted virtualized programs should be storeable
  * ast:io as the only way to interact with host; no leaking of procedures in either direction

* virtualized evaluation
  * host provides the s-expr datum representing a program and has the vm parse it
    * datum is "allocated" in the vm heap, optionally with metadata/provenance
    * datum is then parsed by the vm in some syntactic environment
      * i.e., parse is a vm-level program taking newly-allocated datum as input
      * in this way, env may refer to heap-allocated macros
        * which may embed heap-allocated values as program constants during expansion
          * e.g., quasiquote may embed references to `append` and `list->vector`
  * host can then eval the parse result/AST (also a vm heap value) using a
    safe/resource-budgeted/debuggable/etc. evaluator, with the vm heap as background
    * host can optionally optimize the AST before evaluating it
    * host could also extract the AST heap value, compile the AST, etc.
  * how does the vm's version of parse get installed in the first place?
    * host can run non-vm parse on itself to get its AST, then allocate/install it

* add ast:io
* add AST type general enough to cover dynamic state and delimited control
  * call it something like handle/dynamic/context?
* provide unreliable eq[v] primitive(s)
* provide n-ary vector constructor primitive (but can't lift it as a procedure)

* macro system alternatives
  * unusual systems
    * current system is similar to syntactic closures and "micros"
      * syntax may embed lambdas, which are anonymous parsers
    * staged syntax w/ usual lexical scope, requiring explicit environment management
    * explicit syntax-open/syntax-close
    * hygienic scope/binder static inference
  * standard scheme systems
    * mark/rename
    * implicit/explicit renaming
    * syntactic closures
    * macros-that-work
  * expansion-passing style

* pattern matching for tree structures
  * multiple surface syntaxes
    * quasiquote vs. syntax-rules vs. kitchen sink; guards vs. qualifiers
  * a single low level pattern language
    * should support literals, compound data, and/or/?/app, quasiquote, ellipses, etc.
  * multiple matching algorithms
    * general vs. fast for restricted patterns

* pattern matching for sequences (maybe later when the use is clearer?)
  * maybe limit to context free, aka mu-regular languages/grammars
  * recognition-only vs. accumulation/transformation
  * detecting and exploiting unambiguous grammars

* optional ast:io requests for alloc/free and execute (with operands) arbitrary host-platform code
  * to support dynamic compilation without interpretive overhead
  * need to design compatible calling conventions
  * valid code depends on platform, but interface can be wrapped as a generic dynamic eval

* ensure readable formatting of all code
* internable strings? internable pairs/vectors?
* sorted map (btree?); once there's a clear need

### AST simplification (optional?)
* generated Racket code is currently enormous, partly due to base library
* simple, code shrinking optimizations
  * ast augmentation (introduce astx:let, astx:begin) and normalization
    * `(apply (lambda P _) A) => (let ((p a) ...) _)` via (pbind P A)
      * (pbind P A) => (list (p a) ...)
        * P = (Q . R) & A = (cons B C)|(quote (B . C))
          * (append (pbind Q B) (pbind R C))
        * P = #(Q ..k) & A = (vector R ..k)|(quote #(R ..k))
          * (append (pbind Q R) ..k)
        * P = #f | v
          * (list (P A))
    * `(let (A ... (#f VALUE) B ...) _) => (let (A ... B ...) _)`
    * `(let ((#f X) _ ...) Y) => (begin X (let (_ ...) Y))`
    * lift lets while preserving effect order; e.g., let in let binding:
      `(let (X ... ((v (let (A ...) B))) Y ...) _)` =>  ;; assumes unique var names
      `(let (X ... A ...) (let ((v B) Y ...) _))`
  * context simplification
    * non-last begin context reduces to effects; non-effects eliminated
      * e.g., `(begin (cons (mvector-set! A ...) B) C ...)` =>
              `(begin (mvector-set! A ...) B C ...)`
          and `(begin VALUE _ ...)` => `(begin _ ...)`
    * unreferenced binders become #f; #f-bound values simplify to #t
      * same idea as begin's effect context; dead code elimination
      * try to infer #f-bound-ness across non-inlined procedure application
    * if-condition context reduces to truthiness; more dead code elimination
  * inline tiny procedures (i.e., single constant, variable, or primitive)
  * inline single-apply procedures
  * constant propagation/folding
  * be careful with set! variables
* orthogonal to elaboration

### AST elaboration before converting to SSA
* convert ast:letrec into uses of set! (other translations are possible)
* elaborate set! param matching
* replace set! with mvector-set! so that all variables are immutable
* replace dynamic var and delimited control operators via CPS transform
* elaborate lambda param matching; avoid quadratic growth of error message constants
* lift lambda and pass closure argument explicitly
  * locally bind free variable names as closure-refs
  * replace lambda expressions with closure construction

### Intermediate representation, analysis, transformation, execution

#### CPS-style SSA
Implement SSA as a sea of continuations, inspired by MLton and Guile Scheme.

```
atoms:
  primitive names: p
  variable ids:    v
  block labels:    l
  value ids:       id

SSA:
  identifier: I ::= (v  . I-provenance) | #f
  variable:   X ::= (v  . X-provenance)
  constant:   C ::= (id . C-provenance)
  expression: E ::= (values X ...) | (constants C ...) | (prim p X ...) | (call l X ...) | (apply X X)
  transfer:   T ::= (return E) | (jump E l) | (if v l l)
  block:      B ::= (b-provenance (I ...) T)

atomic constants: c
values: V ::= c | (cons id id) | (vector id ...) | (mvector length) | (closure l fv-count)

heap:
  blocks                = {(l  => B)        ...}
  values                = {(id => V)        ...}
  mvector/closure store = {(id => (id ...)) ...}
  provenance accumulators

env:   ENV ::= {(v => id) ...}
process: P ::= (stuck reason details) | (running id* returns=((l . ENV) ...))

system state:
  IO log      = ((action id ...) ...)
  global heap
  threads, possibly with local heaps
```

* streamline and add new primitives
  * direct vector construction via (prim vector X ...)
  * (closure label fv-slot-count) (closure-set! c i v) (closure-ref c i)
  * mvector-set! returns no values

#### Flow analyses
* support general flow analysis on a graph representation of SSA
  * preorder/postorder numbering
  * predecessor and immediate dominator links
* abstract interpretation
  * effects
    * identity-=: mvector=?, procedure=?
    * type-check: null? boolean? number? string? pair? vector? mvector? procedure?
    * (and (<= 0 I) (< I (vector-length  V)))
    * (and (<= 0 I) (< I (mvector-length M)))
    * (not (= 0 X))
    * (mvector-set! M I X)
    * (mvector-ref M I)
    * diverge
  * labels/procedures
    * static-call-count, closure-count, cont-count, abstract store/IO-log preconditions
  * bindings and references
    * abstract-value, ref-counts: call, mref, mset, identity-=, boolean, escape, use
    * availability and required lifetime
    * return
    * if-condition or argument
    * can these be subsumed by type constraints?
      * as procedure
      * impure: mvector-set!/mvector-ref
    * pure references
      * irrelevant argument to known procedure: e.g. X in ((lambda (#f y) y) X Y)
      * argument to type-testing predicate; use as if-condition
      * argument to procedure or constructor
      * type-specific
        * use as procedure
        * component access: car, cdr, vector-ref
        * arithmetic or other type-specific operator argument
    * escapes
      * different levels of escape
        * full: unknown uses of this value are possible
        * deterministic limited: value-only escapes via known code
        * nondeterministic limited: captured by a known thread
      * argument to unknown procedure
      * procedure return to unknown caller
      * transitive: embedding in escaping value as constructor argument or closure free var

#### Transformations
* remove unreachable blocks
* remove irrelevant mset!s  ; escape/lifetime, no subsequent mrefs
* remove irrelevant labels  ; no jump/call/closure/return-stack
* remove #f-ified bindings  ; pure i.e., no produced-effects
* #f-ify irrelevant vars    ; no refs
* simplify #f-ified sources
* simplify boolean-only sources
* simplify closures
* constant propagate/fold/flatten
* contify single-point returns
* worker/wrapper refactoring
* inline call
* CSE/tieback memoized      ; original label
* reorder blocks            ; commutative produced-effects according to before/after abstract-env
  * not sound wrt removed type-checks without consulting abstract-env
  * need to track abstract env to commute follow-up type-checks
  * might not be necessary for effective tiebacks
  * when supercompiling you'll often want to bring relevant bindings as close to the
    return expr as possible, making it easier to form tieback loops

#### Deciding what to specialize
* parameters: SSA node costs; inlining threshold; conditional/join specialization threshold
* when is a procedure "interesting" to inline?
  * when doing so has no downsides (program does not increase in size)
  * or, if there are downsides, when doing so is reasonably more efficient than not doing so
    efficiency comes from reducing/removing:
      * i/o operations (often hard to prove these are unnecessary)
      * allocation (cons, vector, mvector, closure)
        * unknown call overhead (allocating a structured argument)
        * dead code (code takes up space)
      * indirect data access (car/cdr, vector-ref, mvector-ref, closure-ref, spilled arguments)
        * for one datum, larger difference between 0 and 1 access than 1 and 2, due to caching
      * branching
        * conditionals
        * all call overhead
      * arithmetic operations
  * when it is known to be called exactly once
  * when it has a tiny body; what is tiny?
    * any number of constants or variable references
    * one primitive
      * no matter how small the call signature is
    * no larger than the call signature size
      * sum up the sizes of all primitives, if-statements, and procedure calls (known or unknown)
  * when interesting arguments, or their elements, are known; which ones?
    * known applied closure; even better if the application is interesting enough to inline
    * known cons/vector/mvector being taken apart
    * known numeric operands
    * revealing aggregates/closures that will be taken-apart/applied
    * arguments to a child procedure call that considers them interesting
    * known truthiness of if-statement conditions, which allows removal of dead code
      * particularly when eliminating possibility of bad behavior (e.g., escaping values)
    * interest is lower under if-statements and lambdas (lambdas may be worse)
      * interest can be recovered
        * knowing the truthiness of an if-statement's condition
        * knowing the outgoing lambda will be applied
  * when it's not too boring (too large in an uninteresting way); what is boring?
    * performing IO
    * constructing aggregates/closures that aren't known to be taken-apart/applied
    * calling unknown or boring procedures
  * when doing so won't potentially infinite loop
* when is a join point "interesting" to specialize?

#### Dynamic linking and virtualized execution
* compile SSA to RTL with lower level value/control representations
  * [de]allocate based on linearity/escape analysis
* heap linking
* system state image serialization

### Program virtualization
* program representation
  * global and thread-local heaps
    * transparent values; procedures retain linkable code
    * procedure heap is effectively a giant letrec
  * additional gc roots; migration
  * live threads
    * thread-local heap; cached global heap
      * escaping values/mutations committed to global heap upon sync/preemption
      * thread allocates from a disjoint chunk of heap ids
        * exhaustion forces preemption to obtain a new chunk
    * code can directly reference heap values; allocates ids from same namespace
    * how do they coordinate heap changes? similar to linking?
    * resource-budgeted small-step evaluation of any subset of threads
      * resource control
        * budget time and memory, throttle/suspend/resume/rewind/terminate
        * replicate and distribute
      * failure isolation: optional recovery/repair and resumption
      * incremental/adaptive computation
      * observe a program's internal state while it's running
      * modify a program while it's running
      * symbolic profiling, time-travel debugging, provenance
        * and other forms of analysis and immediate feedback
* how does external state/communication work?
  * what interface with host/io?
* incremental, dynamic compilation and linking with adaptive evaluation
  * can link multiple program states
* persisting program states as images
  * serialize snapshots as (racket) programs that resume from the snapshot point
    * or should this be in some other executable form? executable+data would be nice
  * what processes/state does an image actually persist?
    * all state and processes, except for real devices (or external virtual hardware)
      * real devices can't persist; their drivers involve external processes
    * internal virtual device states and driver processes can be persisted
      * image restart begins with a (boot) process that hooks them up to real devices
* safe compiling of guest programs from source
  * parse.scm syntax error checking that covers all corner cases and contains failure
    * could implement with reset/tag and shift/tag so that errors are catchable
    * could also embed errors within a result, providing more context for better feedback

### Racket platform
* io.rkt capabilities:
  * stdin/stdout/stderr, stty, filesystem, network sockets, gui
  * threads/places/futures, timers, exception/break/interrupt handling
    * uncaught-exception-handler, call-with-exception-handler, exn:break?
  * cmdline/shell/env/subprocesses, racket-eval
* define ports, read, write
  * start with high level ops for now, then reimplement in terms of lower level ops
    * open-input-file, open-output-file, close-input-port, close-output-port, flush-output
    * high level: eof?, printf, write-string, write, read-string, read
    * low level: peek-bytes!, read-bytes!, write-bytes, file-position (via `*` version for safety)
      * store bytes in mvectors; support consolidation into vector of unicode chars
  * include non-device (aka string/byte buffer) ports
    * for when you want a port interface to string-like data
* backend-racket integration
  * runtime compilation with option for immediate execution
    * foreign procedures (capabilities) for using Racket eval and namespaces
      * minimize the surface area; ideally something like: (racket-eval racket-sexpr)
  * ultimately, a platform should abstract away its native language for normal use
    * publicly provide just eval, not racket-eval directly
      * internally, it would compose the frontend with racket-eval
* (virtual) hardware capabilities
  * spectrum of capability granting outcomes and other feedback:
    * no-grant to full-unconditional-grant
    * capability may or may not be recognized
      * host recognizes device, but refuses to grant access
      * host unable to grant because it doesn't understand what you want
* example (virtual) devices
  * timers
  * network
  * storage: typical filesystem vs. something else?
  * speakers, mic, camera
  * keyboard, mouse, other input devices
  * display: terminal, canvas, html, gui widgets, etc.
  * gui sub-windows/frames: multiplexed access to many of the above devices
    * another level of virtualization
* evaluating expressions in a REPL subsumes many activities
  * manipulate data, operate devices, launch and manage concurrent processes
    * read in data, write out data (including taking image snapshots)
  * start a sub-REPL in a new environment via (enter!)
  * reboot into something that isn't the REPL: (exit! START-NEW-PROCESS)
  * halt as a special case of rebooting: exit! with a terminating process
* example text interfaces to try
  * rudimentary REPL using stdin/stdout
  * REPL with persistent state/history (less-style scrolling?)
  * terminal hijacked by ncurses-style UI (with mouse support)

### Reorganize
* reorganize lib/
  * README.md
  * link.scm
  * test.scm
  * modules/
  * eventually cache results?: linked.sdata or linked.bdata

### backend for web/javascript
Define a target AST (micro-js) for javascript-specific simplification/optimization.
* target ASTs will be converted to strings for output or processing by JS `Function`
* data: undefined, null, boolean, number, string, array, object, function; var, ref, set!
* control: if, labelled while, apply, return; labelled continue/break
* consult this list: https://github.com/anko/eslisp/blob/master/doc/basics-reference.markdown#built-in-macros

### Web browser platform
Wrap web features as capabilities and build a runtime system in nScheme.
* e.g., console.log, event handling, DOM manipulation, webRTC, storage, etc.
  * maybe present an interface like SDL or pygame
* Do a shallow wrapping of capabilities in micro-js, and pass them to nscheme
  * Could simplify this with a higher level notation (mini-js) compiling to micro-js
    * if, switch, for, while, do/while, apply, return, continue/break, labels
    * few fancy transformations; maybe for lexical scope; no proper tail calls
    * but must be able to safely interoperate with nScheme
      * create and apply nScheme procedures; manipulate mvectors and other data

### Host system interaction patterns
Real-world (effect) interaction/reaction:
* monolithic, hierarchical, purely functional request handling
  * value: (list 'value val)
  * request: (list 'request payload continuation)
  * continuation: -> (lambda (response) ...)
  * eval: program -> value|request
  * handle: value|request -> ...
* independent processes communicating via shared mvectors
  * arbitrary topology; can support true paralllelism
  * can reason about host system as a concurrent, black box process

### control extensions
* implement tag-aware delimited continuation operators in base language
  * e.g., reset/tag, shift/tag, abort/tag
* delimited control:
  * programs not making use of delimited control should incur no additional overhead
  * for more precise resource control, replace shift/reset with: prompt0, control0, abort
    * should dynamic-put, dynamic-get be primitives for tail call efficient parameterize?
    * maybe exclude delimited control from base language, and implement via CPS-ing
      embedded interpreter; aggressive inlining can recover native stack-like efficiency
  * higher level continuation interface
    * support restartable error handlers (particularly important for REPL support)
    * aborting w/ specific tags
    * parameterize
    * dynamic-wind (but be wary of spurious exit/re-enter cycling
      * should forward dynamic parameters, to avoid exit/re-enter for parent lookup
        * what other kinds of aborts should/can be pre-empted by dynamic-wind in this way?
    * what does Racket really do?
      * exceptions/errors, break (and other interrupts)
        * asynchronous exceptions, like break, don't really make sense
          * Interrupts make more sense in terms of parallel processing, and should be
            designed for explicitly.  An interrupted program that does not explicitly
            ask to handle interrupts should terminate, not raise an exception in an
            arbitrary thread.
          * concepts like "break" belong to the meta-level, not in object-level programs
            * e.g., a main meta-level program (such as an IDE or debugger) is evaluating
              an object-level program when a "break" is signaled.  The interrupt handling
              behaves like a separate thread which communicates a break message to the
              main program thread.  The main program has been designed as an event loop
              that listens for interrupt messages such as "break", and responds by
              suspending its evaluation of the object-level program.
* parallel processing: spawn, (mvector-cas! mv i expected new) => boolean?
  * Is spawn necessary for equational reasoning with multiple processes?  If not, we can
    just expose a threading interface via procedures.  Would such an interface have to be
    platform-specific?  Racket efficiently supports interruption features that JS can't.
  * high level synchronizable actions interface
    * as in Concurrent ML, or Racket synchronizable events

### syntax extensions
* light extensions
  * lambda/match, match
  * lambda-syntax, let[rec]-syntax, define-syntax, define-syntax/define
* definition context conveniences
  * embedded procedures in a definition context that take st as argument
    * #(define ,(lambda (st) ...))
  * ($define (lambda (st) ...)) to directly access state without embedded procs
  * property manipulation shorthand
    * (describe identifier ((property-name value) ...))
    * `(describe* (id*) kvs)`
    * e.g., (describe var ((set! #f))) to hide the capability to set! a variable
  * @definitions-run to force accumulated actions to run, and reset defined names
    * for staging support, defstate needs a continuation stack
  * other ideas for commands:
    (define-set! name form) : eval form and stick in set! prop
    (define-ref  name form) : eval form and stick in ref prop
    ;; some of these don't need to add commands; can perform effect immediately
    (define-syntax name form)
    (define-definition-syntax name form)
    (define-alias name name)
    (declare-syntax names ...)
    (declare-constant names ...)
    (declare-hidden names ...)
    (set-parameter! name form)  ;; dynamic unwinding assignment
    ;; these decompose into (multiple) define(s)
    (define* names ...) ;; define each to #t initially
    (define-vector-type name field ...)

### representation type system
* an alternative design for structural types (inconsistent, needs some cleanup)
  * unit, atom, (dependent sum?) product (n-ary shorthand), sum, fix, fixvar, pointers?
  * atom      A ::= unit | (float ...) | (int ... numeric range/set ...) | (pointer T)
  * mutable?  M ::= A | (mutable A)
  * product   P ::= M | (struct M P) | (exists (n ...). P) | (array N P P)  ;; array of N repetitions of P followed by P
  * recursive R ::= S | (fix x. S) | (fixvar x)
  * sum       S ::= P | (case N (N P) ...)
  * sealed/nominal? witness tag, existential, ...
  * procedure F ::= (-> ...) | (forall n. F) | sealer/unsealer(must be given an underlying type)?
  * ptrtarget T ::= F | R
  * nat       N ::= ... arithmetic expressions ...
  * convenient let expressions and corresponding names/variables, struct-append, etc? or have this be metalevel?
  * example:
    (fix scheme-object. (union (exists n. (int60 n))
                               (*8 (struct scheme-object scheme-object))
                               (*8 (exists n. (struct n (array n scheme-object unit))))
                               (*8 (exists n. (struct n (array n (mutable scheme-object) unit))))
                               (exists c.
                                (fix closure. (*8 (struct (-> (closure scheme-object) (scheme-object))
                                                         (array c (mutable scheme-object) unit)))))
                               (* sealed)))
    * replace union with case mappings (nat-indexed dependent types)
  * name attributes, allow nested structs, allow mutable products as a shorthand for product of mutables?
  * linear types for initialization mutation of to-be-immutable values
  * allocation, initialization, and stack frames
    * shared vs. unique pointers
      * shared mutation must preserve type
      * unique mutation may change type, but may not be copied; similar to registers
  * How are garbage collectable pointers indicated?  Or is everything implicitly gc-able?

* an intermediate representation, but also a lower level user notation
* aliasing/uniqueness annotations
  * e.g., mvector->vector need not copy if the mvector was unique and is no longer used
  * single/multi-threaded aliasing constraints can inform mvector optimizations
    * along with aliasing, infer thread-local and uncontended mvector accesses
* escape/local annotations
  * closures need not be allocated when only used within parent's stack lifetime
  * stack allocations for data with appropriate lifetimes
* maybe some simple effect annotations on procedures
  * parameter aliasing (hoarding away shared references to parameters, increasing their refcount)
  * resource usage:
    * heap/stack allocation
      * heap regions created and/or allocated into, if applicable
      * whether the allocation is temporary (should be for stack) or lasting
        * is this subsumed by region info?
    * termination, time bounds
  * use of shift/abort, set!, mvector-set!
* mix high level and C-like types (could optionally allow unsafe coercion)
  * unknown (only valid when runtime type info is available, e.g. vector element type)
  * tagged (the default dynamic type of tagged pointers and small constants)
    * const: #t #f () char fixnum [u]int8 [u]int16 [u]int32
    * flonum
    * number: bigint rational complex [u]int64
    * string/symbol
    * pair {T T}
    * [m]vector {(struct T ...) | (array N T)}
    * procedure {(T ... [. T]) -> E T} where E is an effect annotation
  * ints, floats, structs, arrays, procedures
  * (struct) is Top, (struct T) :=: T, (struct A B) :<: (struct A)
    * intuitive conversions with array types
  * addresses/pointers
    * (pointer-to T)        ;; typical pointer
    * (pointer-between T T) ;; pointer that knows about data before it
      * (pointer-between A B) is a subtype of (pointer-to B)
* could go beyond C-like types: memory map types that describe hierarchical context
  * individual data structures within the context of larger memory (sub)pages
    * parent alignment allows calculation of parent addresses from child addresses
  * both static and dynamic offsets within a parent context
    * . (dot) or [N] (where N is a literal) is sugar for a static offset
  * AND(&&) and OR(|) types/constraints: OR for something like unions, AND for composing contexts
    * value-dependent constraints
      * for determining sizes, positions, and/or which OR branch is relevant
      * e.g., a tagged pointer where the tag describes what the pointer points to:
        * example-pointer-union = [bits[61]|0b001] && p1-ptr-type | [bits[61]|0b002] && p2-ptr-type
          * would also describe calculation of actual address, masking lower 3 bits
      * length-encoded arrays:
        * dynamic-array = &[N|any[N]]
      * endpoint-encoded arrays:
        * dynamic-array = (word P) && &[end|any[N]] && (N == (end - P) / (type-size any))
  * full control over all memory management, models, and algorithms
    * enough descriptive power to optionally verify implementations
    * e.g., able to describe data in the context of garbage collection metadata
      * page-type = [prev-page|next-page|type-info|gc-marks[N]|words[N]]
      * pointer to datum of type {struct T U}:
        * ptr-type = (word A)
                  && &(page-type.words[N])
                  && &{struct T U}
                  && (N == (A - (address->page-address A)) / (type-size type-info))
        * can define copying/mark-sweep/mark-copy/generational/etc. gc algorithms
      * pointer to pool-allocated datum:
        * pool-page-type = [type-info|allocation-info[N]|obj[N]]
        * pool-ptr-type = (word A)
                        && &obj
                        && &(pool-page-type.obj[N])
                        && (N == (A - (address->pool-page-address A)) / (type-size type-info))
        * can define non-fragmenting pool allocation for same-sized objs
      * size-dependent allocation decisions:
        * maybe-large-array = &[N|any[N]]
                            && ((N >= threshold && &([prev|next|N|any[N]][2]))
                              |(N < threshold  && normal-gc-page-allocated-array)
    * also e.g., allowing call stack layouts to be described explicitly
      * plain example (^ denotes frame pointer) for stack frames [0,1,2]:
        * frame-entry-2     = [^return1|a1|a2|...]
        * frame-returning-2 = [r1|r2|...|^return1|a1|a2|...]
        * frame-returned-1  = [^return0|b1|b2|...|r1|r2|...]
      * explicit frame-specific gc handlers example:
        * frame-entry-2     = [handle-gc1|^return1|a1|a2|...|handle-gc2]
        * frame-entry-1     = [handle-gc0|^return0|b1|b2|...|handle-gc1]
        * could instead map return addresses directly to gc handlers, saving a little space
        * could instead decorate frames with pointer maps and define a single gc handler
      * can define segmented, spaghetti, cactus, etc. stacks
        * can define continuation capturing and resumption
* motivations and example:
  * immediate unboxing, e.g., operating directly on unboxed flonums
  * vector element unboxing
    * vector{flonum} can be represented more efficiently than vector{tagged}
  * statically-known vector-ref access logic
    * vectors store element type tag along with arity at runtime, to inform vector-ref
    * so e.g., a vector{flonum} can still be accessed safely by type-agnostic vector-ref
    * vector-ref can be more efficient when the element type is known
      * even when the type is 'tagged', at least the stored type tag check can be elided
* eventually at the RTL level, would like to define procedures with register pre/post conditions

### other backends to consider
WebAssembly, Python, C, Java, .NET, Erlang, LLVM, x86, ARM, FPGA, ...

### other platforms to consider
Electron, NW.js/Node.js, Python, POSIX, Java, .NET, Erlang, mobile etc., bare metal, ...

### alternative semantics
Support other forms of evaluation using the same syntax:
* functional logic programming
* probabilistic programming
* automatic differentiation

### temporal relational programming
* checked assertions
  * (== x y) :- (p w x) (p w y)
    * w is a unique key
  * (< J K) :- (file-parent J K)
    * filesystems are acyclic
  * (assert (q X)) :- (p X)
    * model checking
* transformation
  * not limited to queries
  * identify smallest set of referenced values per predicate column
    * partition predicate into new predicates when these sets are not Top?
  * negations with ground can sometimes be used recursively: transformation to stratifiable program?
* constructors/functions/aggregations can be used non-recursively
  * sometimes recursively when acyclic
* some infinite relations can be queried when ground:
  * e.g., p(X) :- not q(X); ?p(1)
  * successor/choice; temporal (aka acyclic) stratification
* stating/proving monotonicity
  * idempotent, commutative, associative, possibly between different aggregators
* arbitrary lattices w/ group-by
* <, <=, =/= constraints
* solvers
  * numeric constraint classification: linear, nonlinear, unclassified
* open/closed world caveats
* low level: sccs, fixed-point, relations, join, filter, project, union, difference, aggregate
* evaluation
  * naive, as simple as possible
  * semi-naive; scc dag
  * indexing; join plans; maybe try worst-case optimal joins
    * https://github.com/frankmcsherry/blog/blob/master/posts/2015-04-11.md
* concrete vs. variable join
  * how do you join infinite (but constrained) relations?
    * i.e., constrained variables are mentioned
    * lattice-join the constraints (conservatively)
    * apply those when filtering other (finite) relations for their joins
    * then finally, when joining with the infinite relation, apply the constraints accurately
* possible names: tKanren, underlog, icarus, wilt

### computational logic, building proofs
* proof-checking decision procedure: (proof? proposition candidate-proof) : Boolean
* basic props and inference rules include some minimal mix of: `->, ->*, |->, |->*, ~=`, term induction
  * bracketing (see Boyer-Moore translations) needs reformulation as a meta-level operator
    * requires everything to be quoted another level
    * decision procedures all the way down until term induction
  * term induction
    * a special case of universal quantifier proof (all t:Term. P(t))
      * doesn't require decision procedure for quantifier bounds checking
      * inference rule requires a way to hypothesize smaller induction proofs
  * can BHK interpretation ideas be used to manipulate Boyer-Moore style proofs?
    * BHK versions shown for comparison below are not the same structures as the Boyer-Moore proofs
  * Boyer-Moore style proofs:
```
      p. proof of #"A and B" where
        (proof? #"(and (proof? A ...) (proof? B ...)) ->* #t" p)
        BHK: p = (pair a b) where #"(proof? A a) ->* #t" and #"(proof? B b) ->* #t"
      p. proof of #"A or B" where
        (proof? #"(or (proof? A ...) (proof? B ...)) ->* #t" p)
        BHK: p = (pair 0 a) where #"(proof? A a) ->* #t"
               | (pair 1 b) where #"(proof? B b) ->* #t"
      p. proof of #"all x : S. P(x)" where
        (proof? #"(lam (x)
                    (if (equal? (bracket #t)
                                (step-complete #"(S #,(bracket x))"))
                      (proof? #"P(#,(bracket x))" ... x ...)
                      #t)) ->* (lam (x) #t)"
                p)
        note the bracket operation, which can only exist as a meta-level operation
        extra level of quotation/bracketing necessary to verify well-definedness via step-complete
          if checking "x is an S" gets stuck or infinite loops then all bets are off
            so S pretty much has to be a decision procedure because step-complete is *not*
            bounds checking analogous to type/kind checking
        BHK: p is a dependent product of the same form as described by the proven formula
      p. proof of #"A -> B" where
        (proof? #"(lam (a)
                    (if (equal? (bracket #t)
                                (step-complete #"(proof? A #,(bracket a))"))
                      (proof? B ... a ...)
                      #t)) ->* (lam (a) #t)"
                p)
        It can be seen that #"A -> B" = #"all a:(proof? A). B"
          implies the right BHK interpretation
      p. proof of #"not A" where
        (proof? #"(lam (x)
                    (if (equal? (bracket #t)
                                (step-complete #"(proof? A #,(bracket x))"))
                      'False'
                      #t)) ->* (lam (x) #t)"
                p)
        can be seen as: all x:(proof? A). 'False'
        BHK: substitute any prop 'False' you'd like; if handed a (proof? A), suddenly you've proven 'False'
```

### certified programming
* entirely optional and available at any sub-program granularity
  * no obligation to statically analyze or type-check programs before running
  * selectively analyze/certify/transform important parts of your program later on
* general framework for building reasoning/transformation tools
  * dictates inference rules describing operational semantics
  * everything else should be derivable
* analyses
  * memory safety
  * termination checking
  * effect analysis
  * information flow analysis
  * control flow analysis
  * type checking
  * model checking
* correctness-preserving transformations
  * refactoring
  * optimization, e.g. supercompilation
  * model concrete machines and operate abstract machines
    * simulation
    * compilation
    * analysis and optimization
      * resource analysis and management
        * e.g. region-based memory management: like compile-time garbage collection
      * symbolic profiling
* automated program elaboration
  * inference of types, terms, even tests
* proof-carrying code

### hyperprogramming

## Static approach to fexprs
* referring to this approach as "static"; referring to Kernel's fexprs as "dynamic"
  * in Kernel, applicative behavior is a dynamic property of values via wrap/unwrap
  * in this approach, applicative behavior is a static property of bound names
    * syntactically apparent, determined by how a name is bound
      * e.g., given the form `(f . X)` where `f` is a symbol
        * `f` is bound as operative: apply `f` to `current-env` and literal `X`
        * `f` is bound as applicative: apply `f` to list of evaluated elements of `X`
      * non-symbol heads are treated as applicative
    * any procedure may behave as an applicative or operative without modification
      * all procedures are lambdas without caveats or additional feature complexity
      * e.g., `(apply lambda an-env-that-binds-+ '(x) (list (list '+ 'x n)))`
        dynamically produces a `(lambda (x) (+ x n))` for some runtime value `n`
    * seems both more convenient and easier to reason about than applicative wrappers
    * seems just as expressive as the dynamic approach
* static approach simplifies encapsulation where desired
  * e.g., in the dynamic approach, an operative (called `f`) passed to a higher order
    procedure (such as `map`) will observe the procedure's implementation details; to
    prevent this, `map` would have to runtime-assert that `f` is wrapped (applicative)
  * in the static approach, `map` can bind `f` as applicative, guaranteeing
    the security of its source code without additional checks

## References by topic

### De Bruijn indices and explicit substitutions
* [Wikipedia: De Bruijn index](https://en.wikipedia.org/wiki/De_Bruijn_index)
* [How I learned to stop worrying and love de Bruijn indices](http://disciple-devel.blogspot.ca/2011/08/how-i-learned-to-stop-worrying-and-love.html)
* [Wikipedia: Explicit substitution](https://en.wikipedia.org/wiki/Explicit_substitution)
* Blitz introduction to de Bruijn indices and explicit substitution: [How to implement dependent type theory III](http://math.andrej.com/2012/11/29/how-to-implement-dependent-type-theory-iii/)

### Reduction systems
* [Explicit evaluation](http://fexpr.blogspot.ca/2013/07/explicit-evaluation.html)
* [Continuations and term-rewriting calculi](http://fexpr.blogspot.ca/2014/03/continuations-and-term-rewriting-calculi.html)
* Part II of [Fexprs as the basis of Lisp function application; or, $vau: the ultimate abstraction](https://www.wpi.edu/Pubs/ETD/Available/etd-090110-124904/unrestricted/jshutt.pdf)

### Milawa proof checker implementation
* https://www.cs.utexas.edu/users/jared/milawa/Documentation/defense.pdf
* https://www.cs.utexas.edu/users/jared/milawa/Documentation/dissertation.pdf
* https://www.cs.utexas.edu/users/jared/publications/2015-jar-milawa.pdf
  * terms T; formulas F ::= T=T | not F | F or F
  * appeal (proof step) { method (rule name, such as 'axiom, 'theorem (something already proven), 'expansion (A or B), etc.), conclusion, subproofs, extras }
    * restructure appeal as variant, one alternative per inference rule
  * consider clauses instead of sequents; consider proofs with multiple conclusions

### Low-level verification
* http://plv.csail.mit.edu/bedrock/
* http://adam.chlipala.net/papers/BedrockPOPL15/BedrockPOPL15.pdf

### Theory of changes
* http://www.umut-acar.org/self-adjusting-computation
* http://ttic.uchicago.edu/~pl/sa-sml/
* http://lambda-the-ultimate.org/node/5115

### Live programming
* processes (discrete position updates per time step) vs. equational continuity (motion equations as function of time as if it's yet another spatial dimension on the canvas)
* http://research.microsoft.com/en-us/um/people/smcdirm/apx/
* http://research.microsoft.com/en-us/people/smcdirm/managedtime.aspx
* http://gbracha.blogspot.ca/2008/07/debugging-visual-metaphors.html

### Document-based computing
* https://www.luna-lang.org/
* https://github.com/zot/Leisure
* http://www.quantrix.com/en/
  * https://www.youtube.com/watch?v=LDKI8eeLf2M

### Relational programming
* http://scattered-thoughts.net/blog/2016/10/11/a-practical-relational-query-compiler-in-500-lines/
* http://scattered-thoughts.net/blog/2017/07/28/relational-ui/

### Related work
* [user actions as metaprogramming](https://groups.google.com/forum/#!topic/augmented-programming/gazxhLLXscQ)
* http://bracha.org/objectsAsSoftwareServices.pdf
* https://www.cl.cam.ac.uk/~afb21/CognitiveDimensions/CDtutorial.pdf
* https://en.wikipedia.org/wiki/AgentSheets
* http://openendedgroup.com/field/StandardLibrary.html
* https://web.archive.org/web/20070927190552/http://users.ipa.net/~dwighth/smalltalk/Fabrik/Fabrik.html
* http://arxiv.org/abs/0710.2358
* http://cs.brown.edu/~spr/research/env.html
* https://github.com/bloom-lang/bud/blob/master/docs/operational.md
* http://www.jgrasp.org/
* http://foswiki.cs.uu.nl/foswiki/Proxima/WebHome
* http://www.alice.org/index.php

repository: gregr/ina

repo_name: gregr/ina


text:
#  Thpace

Thpace is a pretty canvas creation of mine. It makes a space animation out of triangles.

[Example](https://www.braedin.com/Thpace/)

# Usage
You can install Thpace through NPM as a module, or through a CDN
## NPM
`yarn add thpace`
 \- or -
 `npm install thpace`

## CDN
`https://unpkg.com/thpace` Will get you the minified build
Then, you can import:
```html
<script src="https://unpkg.com/thpace"></script>
```

##  Ok but like what code do I write to use it?

```js
import Thpace from 'thpace';
// or
const Thpace = require('thpace');
// or, if you used the CDN, skip those

const canvas = document.querySelector('#make-me-cool');

const settings = {
	colors: ['#4CB1EF',  '#424959',  '#FF4B44'],
	triangleSize: 100
};

Thpace.create(canvas, settings);
```

#  Some Info

##  Settings
|Setting|Accepts|Default|Description|
|--|--|--|--|
|`triangleSize`|number|`130`|Triangle size (px)|
|`bleed`|number|`120`|Bleed amount over canvas edges (px)|
|`noise`|number|`60`|Noise used when calculating points (px)|
|`colors`|Array\<string>|`['rgba(11,135,147,1)', 'rgba(54,0,51,1)']`|Array of colors to use for the gradient|
|`pointVariationX`|number|`20`|How much the points should shift on the x-axis (px)|
|`pointVariationY`|number|`35`|How much the points should shift on the y-axis (px)|
|`pointAnimationSpeed`|number|`7500`|How fast the points should complete a loop (ms)|
|`image`|HTMLImageElement|`undefined`|Overlay image (adds a nice texture)|
|`imageOpacity`|number|`.4`|Overlay image opacity|

license: Unlicense

repository: AlanGreene/Thpace

branch_name: refs/heads/master

extension: md

license_type: permissive

repo_name: AlanGreene/Thpace


text:
# alarmRetarder

alarmRetarder is a small tool, that receives alarm messages using a specified receiver (e.g. via SNMP traps), reduces identical messages and schedules them for forwarding. The forwarding of messages will be delayed using a configured value (e.g. 60 seconds). A configured forwarder (e.g. sending SMS) will be used to send alarm messges to the target.

Each alarm message containes the following fields:
* ID
* type (1 = problem, 2 = resolution)
* severity
* timestamp
* key
* logmessage

Each alarm message has a type, which could be "problem" (1) or "resolution" (2). A problem means, that there is something, which needs attention. All alarm messages of type problem with the same key will be reduced to one. A resolution alarm message resolves a problem alarm message with the same key.

If a problem alarm message occurs, it will be delayed using the configured interval. If the problem is resolved (with a resolution alarm message) within that interval, the message will not be forwarded to the user.

The tool was designed for the network management plattform OpenNMS and the SNMP trap northbounder (OpenNMS version 17.1.0 or higher), but may be useful for other use cases, too.

## Usage

### Start a Docker Container
There is a Docker Image on Docker Hub. alarmRetarder is installed in /opt/alarmRetarder with its default configuration. If you want to use your own configuration, map your own configuration file in the container with volumes.

Please hava a look at the following docker-compose.yml example:
```
version: "2"
services:
  alarmretarder:
     image: michaelbatz/alarmretarder
     volumes:
      - ./data/alarmretarder/etc/config.conf:/opt/alarmRetarder/etc/config.conf
      - ./data/alarmretarder/logs:/opt/alarmRetarder/logs
```

### Manually setup your environment
alarmRetarder is written in Python3 and all you need, are the following libraries:
* pysnmp4
* requests

If all the libraries are installed, simply execute main.py and alarmRetarder is running:
```
./main.py
```

## Documentation
The documentation is provided with the tool and can also seen on [GitHub](https://github.com/michael-batz/alarmRetarder/blob/master/docs/src/documentation.adoc)

## Support
Please use the issues on the [GitHub project](https://github.com/michael-batz/alarmRetarder "alarmRetarder on GitHub") for bugs, enhancement requests and support questions.

license: MIT

repository: michael-batz/alarmRetarder

repo_name: michael-batz/alarmRetarder


text:
# This Week in Enhancements - 2022-02-11

*Updates since 2022-02-04*

## Enhancements

### Merged Changes

*<PR ID>: (activity this week / total activity) summary*

There was 1 Merged pull request:

- [1021](https://github.com/openshift/enhancements/pull/1021): (36/88) machine-api: [OCPCLOUD-1377] Add "Azure Ultra Disks support in Machine API" enhancement (damdo)

  > Enable OCP users to leverage [Azure Ultra Disks](https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#ultra-disks) on Machine API provisioned hosts on Azure via Data Disks or to attach them to Machines via Persistent Volumes (PVs).

### New Changes

*<PR ID>: (activity this week / total activity) summary*

There were 5 New pull requests:

- [1027](https://github.com/openshift/enhancements/pull/1027): (2/2) general: Enable ProjectRequestLimit on OpenShift 4.x (josefkarasek)

  > The `requestlimit.project.openshift.io/ProjectRequestLimit` admission plugin is used to impose a limit on the number of
  > self-provisioned project(s) requested by a given user/service account. In 3.x, the limit can be specified via the master configuration file.
  > It doesn't fit well with our targeted configuration which aims to avoid adding lots of intricately documented knobs.
  > This is why this admission plug-in is disabled in OpenShift 4.x.
  >
  > Instead of wiring the admission plugin via the `openshift-apiserver` operator, we can create a validating admission webhook
  > based on the [generic-admission-server](https://github.com/openshift/generic-admission-server) and distribute it via
  > OperatorHub/OLM.

- [1028](https://github.com/openshift/enhancements/pull/1028): (11/11) cluster-logging: flow-control-api spec (pmoogi-redhat)

  > If the log collector cannot keep up with the rate that logs are written, some logging data will be lost.
  > Lack of  flow control these problems:
  > * Hard to predict and impossible to control the volume of logs.
  > * No control over which logs get lost.
  > * During an outage, log buffers build up without user control.
  >   This can cause long recovery times and very high latency when the connection is restored.
  >
  > This proposal defines an API to let cluster administrators to limit logging rates, or ignore some logs entirely.
  > Logs may still be lost if the collector cannot keep up, but administrators have more control over *what* is lost,
  > and more predictability of log rates.

- [1029](https://github.com/openshift/enhancements/pull/1029): (187/187) network: OVN-Kubernetes on Hypershift (squeed)

  > [Hypershift](https://hypershift-docs.netlify.app/) is a new deployment model for OpenShift which removes the requirement that clusters be "self-hosted". Rather, a given hosted cluster's control plane actually resides as pods on another "management" cluster.
  >
  > Adapting the OVN networking plugin to the Hypershift model requires some careful design. Specifically, OVN provides its own control plane and datastore, all of which will be hosted external to the hosted cluster.
  >
  > Thus, the OpenShift OVN deployment model must be updated to support split control planes. Likewise, the Network Operator must be able to manage components on both the control plane as well as the hosted cluster.

- [1030](https://github.com/openshift/enhancements/pull/1030): (10/10) monitoring: enhancements/monitoring: User-Defined Alerting and Relabeling Rules (bison)

  > The core OpenShift components ship a large number of Prometheus alerting rules.
  > A 4.10-nightly cluster on AWS currently has 175 alerts defined by default, and
  > enabling additional add-ons increases that number.  Still, users have repeatedly
  > asked for a supported method of adding additional custom rules, adjusting
  > thresholds, or adding and modifying labels on existing platform alerting rules
  > -- for example, changing severity labels.
  >
  > These modifications are currently not possible, because the alerts are managed
  > by operators and cannot be modified, and the addition of custom rules is
  > explicitly unsupported at the moment.  This proposal outlines a solution for
  > allowing additional user-defined rules and relabeling operations on existing
  > platform alerting rules.

- [1032](https://github.com/openshift/enhancements/pull/1032): (2/2) general: OpenShift CoreOS Layering (provisional) (cgwalters)

  > Change RHEL CoreOS as shipped in OpenShift to be a "base image" that can be used as in layered container builds and then booted.  This will allow custom 3rd party agents delivered via RPMs installed in a container build.  The MCO will roll out and monitor these custom builds the same way it does for the "pristine" CoreOS image today.
  >
  > This is the OpenShift integration of [ostree native containers](https://fedoraproject.org/wiki/Changes/OstreeNativeContainer) or [CoreOS layering](https://github.com/coreos/enhancements/pull/7) via the MCO.

### Active Changes

*<PR ID>: (activity this week / total activity) summary*

There were 16 Active pull requests:

- [1008](https://github.com/openshift/enhancements/pull/1008): (52/185) machine-api: [OCPCLOUD-1248] Add initial iteration of ControlPlaneMachineSet operator enhancement (JoelSpeed)
- [1025](https://github.com/openshift/enhancements/pull/1025): (46/47) kube-apiserver: Introduce detection of stale clusteroperator conditions (mfojtik)
- [1014](https://github.com/openshift/enhancements/pull/1014): (38/265) multi-arch: Heterogeneous architecture clusters (Prashanth684)
- [995](https://github.com/openshift/enhancements/pull/995): (36/225) machine-api: Add enhancement for AWS Placement Groups in Machine API (JoelSpeed)
- [1010](https://github.com/openshift/enhancements/pull/1010): (21/42) authentication: add enhancement on PSa autolabeling (stlaz)
- [996](https://github.com/openshift/enhancements/pull/996): (18/176) single-node: Enhancement for enabling single-node-openshift with workers (omertuc)
- [952](https://github.com/openshift/enhancements/pull/952): (18/44) ingress: NE-585 Expose HealthCheck Interval (candita)
- [1009](https://github.com/openshift/enhancements/pull/1009): (16/71) general: OpenStack Cloud Provider Config Upgrade (stephenfin)
- [1020](https://github.com/openshift/enhancements/pull/1020): (9/98) ingress: Add enhancement for AWS Load Balancer operator (arjunrn)
- [987](https://github.com/openshift/enhancements/pull/987): (8/74) dns: Add the DNS-over-TLS enhancement initial draft (brandisher)
- [1023](https://github.com/openshift/enhancements/pull/1023): (5/9) ingress: Add route-subdomain enhancement (Miciah)
- [958](https://github.com/openshift/enhancements/pull/958): (5/108) monitoring: enhancements/monitoring: User-defined alerting rules proposal (bison)
- [943](https://github.com/openshift/enhancements/pull/943): (4/110) etcd: [OCPCLOUD-1244] Add proposal for etcd protection mechanism during control plane scaling (JoelSpeed)
- [981](https://github.com/openshift/enhancements/pull/981): (2/136) general: Added proposal for HyperShift monitoring. (bwplotka)

#### Active Pull Requests Modifying Existing Documents

- [1000](https://github.com/openshift/enhancements/pull/1000): (45/152) api-review: Update enhancement proposal to support update of user-defined AWS tags  (TrilokGeer)
- [1017](https://github.com/openshift/enhancements/pull/1017): (1/15) helm3: helm: fix example in the documentation (zonggen)

### Closed Changes

*<PR ID>: (activity this week / total activity) summary*

There was 1 Closed pull request:

- [1013](https://github.com/openshift/enhancements/pull/1013): (1/6) cluster-logging: LOG-1043 Flow control API enhancements. (alanconway)

### Revived (closed more than 7 days ago, but with new comments) Changes

*<PR ID>: (activity this week / total activity) summary*

There were 3 Revived (closed more than 7 days ago, but with new comments) pull requests:

- [243](https://github.com/openshift/enhancements/pull/243): (3/187) general: Enable ProjectRequestLimit on OpenShift 4.x (tkashem)
- [725](https://github.com/openshift/enhancements/pull/725): (1/50) distributed-tracing: Allow/Expose options to enable distributed tracing in components as features are added upstream  (sallyom)
- [924](https://github.com/openshift/enhancements/pull/924): (1/221) oc: CLI Manager (deejross)

### Idle (no comments for at least 7 days) Changes

*<PR ID>: (activity this week / total activity) summary*

There were 13 Idle (no comments for at least 7 days) pull requests:

- [745](https://github.com/openshift/enhancements/pull/745): (0/131) security: Security Profiles Operator integration in OpenShift (JAORMX)
- [811](https://github.com/openshift/enhancements/pull/811): (0/71) network: Enhancement proposal for OVN secondary networks (maiqueb)
- [918](https://github.com/openshift/enhancements/pull/918): (0/92) installer: vsphere: add multiple datacenter and clusters (jcpowermac)
- [929](https://github.com/openshift/enhancements/pull/929): (0/226) api-review: [OCPNODE-747] New CRD ImageDigestMirrorSet and ImageTagMirrorSet to support AllowMirrByTags (QiWang19)
- [931](https://github.com/openshift/enhancements/pull/931): (0/74) dns: NE-367: Add logLevel and operatorLogLevel APIs for DNS  (miheer)
- [937](https://github.com/openshift/enhancements/pull/937): (0/131) monitoring: support configuration of alerting notifications by application owners (simonpasquier)
- [992](https://github.com/openshift/enhancements/pull/992): (0/16) authentication: auth: add enhancement for direct kube-apiserver oidc config (stlaz)
- [994](https://github.com/openshift/enhancements/pull/994): (0/7) authentication: auth: add enhancement about pinning SCCs to pods (stlaz)
- [1002](https://github.com/openshift/enhancements/pull/1002): (0/78) ingress: CFE-10: Add host-network-bind-options (Elbehery)
- [1005](https://github.com/openshift/enhancements/pull/1005): (0/54) update: Synchronized upgrades in DPU clusters (danwinship)
- [1006](https://github.com/openshift/enhancements/pull/1006): (0/3) storage: CSI Inline Ephemeral Volume Security (adambkaplan)
- [1019](https://github.com/openshift/enhancements/pull/1019): (0/19) node-tuning: Enhancement for improving image pull via shortname security (umohnani8)

#### Idle (no comments for at least 7 days) Pull Requests Modifying Existing Documents

- [1003](https://github.com/openshift/enhancements/pull/1003): (0/2) authentication: add log level, stage and request uri mask (ibihim)

### With lifecycle/stale or lifecycle/rotten Changes

*<PR ID>: (activity this week / total activity) summary*

There were 3 With lifecycle/stale or lifecycle/rotten pull requests:

- [812](https://github.com/openshift/enhancements/pull/812): (1/57) node: Add proposal about Node Operator (saschagrunert)
- [980](https://github.com/openshift/enhancements/pull/980): (3/74) authentication: enhancements/authentication: detect invalid certificates (s-urbaniak)
- [986](https://github.com/openshift/enhancements/pull/986): (1/5) windows-containers: WIP WINC-712: Windows CSI Storage Enablement (alinaryan)

repository: openshift/enhancements

gha_language: Go

repo_name: openshift/enhancements


text:
VistAViewer
============

VistAViewer is a VistA developer tool that helps exploring various VistA components in a web-browser. It is an application written using EWD.js. User can review VistA patches(builds) and VistA Kernel components - Remote Procedure Calls (RPC), Data Dictionaries, Rouitnes, Options, Security Keys, Parameters, etc. User can test VistA RPC.

For installation instruction and description refer to
http://nikolaytopalov.wordpress.com/2014/05/15/vista-viewer

repository: nikolaytopalov/VistAViewer

repo_name: nikolaytopalov/VistAViewer


text:
# Typescript partial

A small demo project that implements a very simple particle system using [TypeScript](http://www.typescriptlang.org/).

## Implementation
The application is implemented as a very simple HTML page. This page contains a canvas element to which particles are rendered. The actual particle system is implemented in TypeScript. The main advantage of using TypeScript is that it allows you to program in a way that is very familiar to other object-oriented languages (such as C# and Java). You can thus define interfaces, classes, getters, setters and much more. Another big advantage is that you get compile-time type-safety, which is great for catching errors early.

### Structure

The main entry point of the application is the [Scripts/app.js] file, which is generated from [Scripts/app.ts](Scripts/app.ts). Here we setup the application by creating an instance of the `AppViewModel` class, which we then use to bind to [Knockout](http://knockoutjs.com/) when the document is ready:

```javascript
$(document).ready(function () {

    // Create the view model and apply its bindings to knockout
    var viewModel = new AppViewModel();
    ko.applyBindings(viewModel);

});
```

The `AppViewModel` class will create a `Particles` instance in its constructor. This `Particles` instance will be rendering the individual particles to the screen. This rendering to the screen is done by rendering to a `HTMLCanvasElement`, which is asked for a 2D rendering context:

```typescript
var canvas = <HTMLCanvasElement>$('#particlesCanvas')[0]; // Do type-casting of the return value
var ctx = canvas.getContext('2d');
```

After the rendering context has been requested and the particles have been created, we start the image loop by requesting the animation frame and calling the `draw()` method of the `Particles` instance.

### Modules

The application consists of several TypeScript files, which are defined as [AMD modules](http://en.wikipedia.org/wiki/Asynchronous_module_definition). Once a module is defined as an AMD module, it can easily be used by any other module. This allowed us to separate functionality in different files, just like you would do in other object-oriented languages. To enable modules to be reference other AMD modules, you need to include the [RequireJS](http://requirejs.org/) library in your project. Including RequireJS is done in our **index.html** file as follows:

```html
<script data-main="Scripts/app" type="text/javascript" src="Scripts/libs/require.min.js"></script>
```

You see that a **data-main** attribute is specified. This attribute is used by RequireJS to determine the entry point of our application (in our case the [Scripts/app.js](Scripts/app.js) file). This TypeScript files includes other modules using the following, simple code:

```typescript
import Drawing = module('drawing');
import Particles = module('particles');
import Particle = module('particle');
```

The names of the modules are the names of the TypeScript files, so the **'drawing'** module refers to the code defined in the **drawing.ts** file. In that file, the `Drawable` class is defined as follows:

```typescript
export class Drawable implements IDrawable {
   ...
}
```

Due to the class being prefixed with the `export` keyword, it will be available when other modules import the _drawing_ module. If you use the correct module export functionality in TypeScript, it will output the following code when compiling the `Drawable` class:

```javascript
define(["require", "exports"], function(require, exports) {
    var Drawable = (function () {
        function Drawable(ctx) {
            this.ctx = ctx;
        }
        Drawable.prototype.draw = function () {
        };
        return Drawable;
    })();
    exports.Drawable = Drawable;
})
```

One can see that the code starts with a call to the `define` function, which is part of the RequireJS library. Now that the `Drawable` class is correctly registered as an AMD module, the aforementioned `import Drawing = module('drawing');` code will return the drawing module containing the `Drawable` class. After import the the _drawing_ module, one can refer to the `Drawable` class as follows: `Drawing.Drawable`.

### Rendering
As said we use the canvas for rendering and request an animation frame to do periodic rendering. One problem is that the default method, `requestAnimationFrame`, is not available in all browsers. Erik Moller from Opera created a [simple piece of code](http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating) that adds a simulated version of requestAnimationFrame for browsers that don't support it. We include this code in our application in the [Scripts/animation.js](Scripts/animation.js) file.

## Libraries
This project uses the following libraries:

* [TypeScript](http://www.typescriptlang.org/): for writing our JavaScript code in.
* [jQuery](http://jquery.com/): for retrieving elements and its `document.ready()` method.
* [Knockout](http://knockoutjs.com/): for easy data-binding and event handling.
* [RequireJS](http://requirejs.org/): for the loading of our code in different modules.

## License
[Apache License 2.0](LICENSE.md)

repository: ErikSchierboom/typescriptparticles

repo_name: ErikSchierboom/typescriptparticles


text:
# Cloud-native Architecture workshop
In most workshops you start from scratch, but in this workshop you will actually start with a complete working solution called Pitstop. You will learn by executing several labs in which you will be adding functionality to the solution.

Pitstop is an open-source .NET sample application that demonstrates the following software-architecture aspects:

- Microservices
- Event-driven architecture
- Domain Driven Design
- Onion architecture
- CQRS
- Event-sourcing

Also, Pitstop demonstrates how to develop and deploy applications using Docker containers.

# Prerequisites
There are some prerequisites for this workshop:

## Software

First you need an active Internet connection. Additionally you will need to install the following software on your laptop:

- Git ([download](https://git-scm.com/))
- .NET 5 SDK ([download](https://dotnet.microsoft.com/download/dotnet/5.0))
- Visual Studio Code ([download](https://code.visualstudio.com/download)) with at least the following extensions installed:
  - [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp)
- Docker for desktop ([download](https://www.docker.com/products/docker-desktop))
  - During the installation of Docker, do not switch to Windows containers. We will only use Linux containers.

All scripts in the instructions are Powershell scripts. If you're working on a Mac, it is recommended to install Powershell for Mac:

- Powershell for Mac ([instructions](https://docs.microsoft.com/nl-nl/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7.1))

## GitHub account

If you do not already have a Github account, create one by going to the [Github website](https://www.github.com/) and click on the *Sign up* link in the top right corner. Make sure you are logged into Github with your account.

## PowerShell

Make sure you can execute PowerShell scripts.

1. Open an elevated PowerShell prompt.

1. Execute the following command:

   ```Powershell
   Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
   ```

# Labs
In order to complete the labs, make sure you read (at least) the following sections of the [Pitstop wiki on Github](https://github.com/EdwinVW/pitstop/wiki):

- [Start page](https://github.com/EdwinVW/pitstop/wiki/Home)
- [Application functionality](https://github.com/EdwinVW/pitstop/wiki/Application%20functionality)
- [Domain description](https://github.com/EdwinVW/pitstop/wiki/Domain%20description)
- [Solution architecture](https://github.com/EdwinVW/pitstop/wiki/Solution%20Architecture)
- [Technology used](https://github.com/EdwinVW/pitstop/wiki/Technology%20used)

By now, you should have an understanding of what the Pitstop solution contains and what functionality it offers. Next you will execute several lab assignments in which you will add stuff to the Pitstop solution.

> TIP: When you copy/paste stuff from the lab descriptions, please double-check whether you copied an additional whitespace at the end. In some sitiuations this can lead to issues.

## Lab 1: Run the applicaton
In this lab we'll make sure you can run Pitstop on your machine.

For this to work, you must have installed the Git client (see Step 0.1).
1. Open your browser and navigate to the Pitstop repo on Github: https://github.com/edwinvw/pitstop.
2. Click the *Fork* button.
3. The repo is forked to your Github account. If you have multiple accounts, Github will ask which account to fork to.
4. Click the green *Clone or download* button on the forked repo. A dialog is shown.
5. Copy the repo URL to the clipboard.
6. Open Visual Studio Code on your machine.
7. Give the clone repo command by pressing `CTRL-Shift-P`, typing `Git Clone` and pressing `enter` to confirm. You will be asked to specify a repo URL.
8. Paste the copied repo URL in the text-box and press `enter` to confirm.
9. You will be asked to specify a folder for cloning the repo into. Select a folder and confirm. The repo will be cloned in this folder.
10. When VS Code asks you to open the cloned repo, do that. Now you can start working with the repo.

This would be a good time to walk through the solution and see what's in there. In the Wiki of the repo, you can find an overview of the solution structure.

### Step 1.2: Build the Docker images
In order to build the Docker images, follow the instructions in the 'Building the Docker images' section in the repo's Wiki.

### Step 1.3: Run the application
In order to run the application, follow the instructions in the 'Starting the application' section in the repo's Wiki.

### Step 1.4: Get to know the solution
In order to get to know the functionality of the application, make sure you have read the introduction of the solution in the repo's README file up to the *Technology* section. After that, follow the 'Testing the application' section in the repo's Wiki.

## Lab 2: Add an event-handler for customer events
When something happens within the Pitstop application that could be interesting for other parts of the system, an event is published to the message-broker. For instance: when a new customer is registered, a *CustomerRegistered* event is published.

In this lab you will add a service to the solution that will react to customer events. What we will do when the event is received is up to your imagination. For the workshop, we will keep it simple and just dump a message on the console.

The service we will build offers no API and can therefore be a simple console application (just as the existing *NotificationService* for instance).

### Step 2.1: Create the .NET 5 application
First we will add a new service to the solution.

1. Open a command-prompt or Powershell window.
2. Make sure you are in the `src` folder within the Pitstop repository.
3. Use the `dotnet new` command to create a new .NET console application named *CustomerEventHandler*:
   ```
   dotnet new console -o CustomerEventHandler
   ```
   The output should look something like this:

   ![](img/dotnet-new-customereventhandler.png)

A new *CustomerEventHandler* folder will be created which contains a .NET project. Because the created project-type is a console application, the folder will only contain a project file (*CustomerEventHandler.csproj*) and a main program file (*Program.cs*). The default implementation generated by `dotnet new` is printing *'Hello World!'* to the console.

You can test the application by running it:

```
cd CustomerEventHandler
dotnet run
```

The output should look like this:

![](img/dotnet-run-customereventhandler.png)

### Step 2.2: Create event-handler
Now that you've added a new .NET project to the solution, you can start implementing the business logic of the service. As stated, the 'business logic' will be fairly simple for this workshop.

**2.2.1: Open the project in VS Code**
Let's open Visual Studio Code to start coding:

1. Start Visual Studio Code.
2. Select *File*, *Open Folder* and select the *CustomerEventHandler* folder you created in step 3.1.
   >Visual Studio Code might show you some dialogs about plugins that you can install. For now, just install all plugins that it suggests. It will also asks you to add some 'assets' it needs for building and debugging the project. Acknowledge this with 'Yes'. This will create a '.vscode' folder. You can ignore that folder for now.

3. Open the file *CustomerEventHandler.csproj* by double-clicking on it. This is the file that describes the project. It is pretty straightforward and clean.
4. Start the application by pressing `F5`. The project will be built and started. You can see the output in the 'DEBUG CONSOLE' window that was automatically opened.

**2.2.2: Add reference to the infrastructure package**
The CustomerEventHandler service will need to receive messages from the message-broker. I have created a nuget package (*Pitstop.Infrastructure*) that contains a library that will make it easy to implement this without any specific knowledge about RabbitMQ (the broker that is used in the solution).

You need to add a reference to the *Pitstop.Infrastructure.Messaging* nuget package. Execute the following steps to add a reference to the package:

1. Open the terminal window in Visual Studio Code using the *Terminal* menu.
2. Type the following command in this window: `dotnet add package PitStop.Infrastructure.Messaging`.
3. Visual Studio Code will detect changes in the references and automatically restore the references.

**2.2.3: Add event definition**
Now you can start adding some business logic. First you need to add the definition of the events you want to handle. All messages that are sent over the message-broker are plain JSON. The *CustomerRegistered* event is defined as follows:

```JSON
{
	"messageId": "guid",
	"messageType": "string",
	"customerId" : "string",
	"name": "string",
	"address": "string",
	"postalCode": "string",
	"city": "string",
	"telephoneNumber": "string",
	"emailAddress": "string"
}
```

You need to define a C# class to hold this information. We will only use the *customer id* and *name* properties in our code, so in your event-definition you can skip the other customer properties.

The infrastructure package you referenced in the previous step contains an *Event* base-class for events. This class inherits from the *Message* base-class which contains the *MessageId* and *MessageType* properties (the message-type is inferred from the name of the class).

1. Add a new *CustomerRegistered* class to your project.
2. Derive this class from the Event base-class in the *Pitstop.Infrastructure.Messaging* library.
2. Add the implementation of the event-class that only contains the *customerId* and *name* property of the customer.

**2.2.4: Add a *CustomerManager* class that handles events**
Now that you have a definition of the event, you will add a *CustomerManager* class that will get the events from the message-broker and handles them. The polling for messages and the handling of a message when it's available are abstracted in two separate interfaces: *IMessageHandler* and *IMessageHandlerCallback*. They are both defined in the infrastructure package.

The *IMessageHandler* interface abstracts the polling for messages on a message-broker. An implementation of this interface will be passed into your *CustomerManager*'s constructor. The infrastructure package also contains an implementation of this interface that works with RabbitMQ.

When you want to start listening for messages, you have to call the *Start()* method on this interface and pass in an implementation of the *IMessageHandlerCallback* interface. The *HandleMessageAsync()* method is called on the callback implementation when a message is available on the message-broker. The *CustomerManager* will implement this interface and handle the events.

This is a class diagram of this pattern:
![](img/messaging-cd.png)

1. Add a new *CustomerManager* class to your project.
2. Add the implementation that handles *CustomerRegistered* messages. For this workshop it doesn't have to be an elaborate handler. Just dump the received message on the console for example. You can reference other event-handlers (e.g. *AuditlogService*) for inspiration.

**2.2.5: Start the customermanager**
Now that you created a *CustomerManager* that can handle *CustomerRegistered* events, you need to start this manager form the main program. You will use the *RabbitMQMessageHandler* class from the infrastructure package to pass into the *CustomerManager*.

1. Open the *Program.cs* file in the project.
2. Replace the existing code with the necessary code to setup and start the event-handler. You can reference other event-handlers (e.g. *AuditlogService*) for inspiration.

**2.2.6: Add supporting files**
You need some supporting files (things like settings etc.) in order to run the service.

1. Copy the `appsettings.*.json` files from the *AuditlogService* to your project folder and change the contents:
   - Change the value of the *Queue* setting in the RabbitMQ configuration block to `CustomerEventHandler`.
   - Remove the *Auditlog* section.
2. Copy the `Properties/launchsettings.json` file from the *AuditlogService* to a `Properties` folder in your project folder.
3. Add the following snippet to your `.csproj` file:
   ```xml
      <ItemGroup>
      <Content Include="appsettings.Development.json">
         <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
         <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      </Content>
      <Content Include="appsettings.json">
         <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      </Content>
      <Content Include="appsettings.Production.json">
         <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
         <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      </Content>
   </ItemGroup>
   ```
4. Make sure you have referenced the necessary NuGet packages in your `.csproj` file (see the `.csproj` file of the *AuditlogService* for reference).
5. Copy the `.dockerignore` file from the AuditlogService to your project folder.

**2.2.7: Build the code**
In order to check whether or not you made any mistakes until now, build the code. Do this by pressing `Ctrl-Shift-B` in Visual Studio Code and choosing the task *Build*. The output window should look like this:

![](img/vscode-build.png)

### Step 2.3: Run the service
We can start the *CustomerEventHandler* to test whether or not it works.

1. Make sure you have the Pitstop application running on your machine (as described in Step 1.3: Run the application).
2. Open a command prompt or Powershell window and go to the *CustomerEventHandler* folder.
3. Start the application by giving the following command: `dotnet run`.
4. Open the browser and go to http://localhost:7000 to open the Pitstop web-app.
5. Go to the *Customer Management* tab and register a new customer.

Watch the output window of your *CustomerEventHandler*. You should see that a message is printed to the console, something like this:

![](img/dotnet-run-customereventhandler-broker.png)

That's it! You have now created a new service that can react on events emitted by the services in the Pitstop solution. Pretty sweet!

### Step 2.4: Create Docker image
Now that you have created a functional service, let's run it in a Docker container.

1. Add a new file to the project named *Dockerfile*.
2. Copy the contents of the dockerfile of the *AuditlogService* and make sure it starts the CustomerEventHandler (in the ENTRYPOINT statement).

> Please take some time to go over the Dockerfile now. You see an example of the Docker multi-stage build mechanism.
> - First it starts in a container that is based on an image that contains the full .NET SDK (*mcr.microsoft.com/dotnet/sdk:5.0*). We call this *build-env* for later reference.
> - After that it sets the folder */app* as the current working-folder for the build. It copies the *.csproj* file of your project into to the working-folder.
> - Then it restores all the dependencies by running `dotnet restore`.
> - After the restore, it copies the rest of the files to the working-folder and publishes the application by running `dotnet publish -c Release -o out`. It builds the *Release* configuration and outputs the result in the folder *out* within the working-folder.
> - Now it starts the second phase which runs in a container based on the .NET run-time container (*mcr.microsoft.com/dotnet/runtime:5.10*). This container does not contain the entire .NET SDK - so it's much smaller.
> - It then copies the output from the other build phase (that was called *build-env*) to the local folder within the container.
> - Finally it specifies the entry-point - the command to execute when the container starts. In this case it specifies the command `dotnet` and as argument the assembly that was created during the build. This will start the *CustomerEventHandler* console application you've created.

Now you are going to build a Docker image using the Dockerfile.

1. Open a command prompt or Powershell window and go to the *CustomerEventHandler* folder.
2. Build a Docker image by entering the following command:

	`docker build --rm -t pitstop/customereventhandler:1.0 .`

   > You specify the name of the image using the *Tag* option (`-t`).
3. Check whether the image is created by entering the following command: `docker images`:

   ![](img/docker-images.png)

### Step 2.5: Run the service in a Docker container
Now that you have the Docker image, you can start a container based on this image.

1. Run a Docker container based on the image by entering the following command:

	`docker run -it --rm --network src_default --name customereventhandler pitstop/customereventhandler:1.0`

   >In this command you specify the virtual network to connect with. In this case we specify the name of the default network that was created by docker-compose when we started the solution (*src_default*). By doing this, the container can find and access the RabbitMQ server that is running in a separate Docker container on the virtual network.
2. Open the browser and go to http://localhost:7000 to open the Pitstop web-app.
3. Go to the *Customer Management* tab and register a new customer.

Watch the output of your running container. You should see that message again that indicates that a customer was registered:

![](img/docker-run.png)

**Before you continue, stop the running container by pressing `Ctrl-C`.**

### Step 2.6: Run the service using docker-compose
The last step in this lab is to extend the docker-compose file to include your service.

1. Open the *docker-compose.yml* file in the *src* folder of the Pitstop repo in Visual Studio Code.
2. Add this snippet to the *docker-compose* file just before the webapp part:

   ```
     customereventhandler:
       image: pitstop/customereventhandler:1.0
       build: CustomerEventHandler
       container_name: CustomerEventHandler
       depends_on:
         - rabbitmq
       environment:
         - DOTNET_ENVIRONMENT=Production
   ```
3. Save the file.
4. Open the Powershell window where you started the solution using `docker-compose up`.
5. Stop the running solution by pressing `Ctrl-C` and wait until all the containers are stopped.
6. Restart the solution by giving the command: `docker-compose up`. The *CustomerEventHandler* will be started together with all the other services.
2. Open the browser and go to http://localhost:7000 to open the Pitstop web-app.
3. Go to the *Customer Management* tab and register a new customer.

Watch the docker-compose logging in the console. You should see that message again that indicates that a customer was registered:

![](img/docker-compose-output.png)

>The following labs are more advanced labs you can do on your own if you're done with the first two labs. There's no extensive description on how to complete these labs, only a description of the required outcome. It's up to you to figure out the best way to implement these requirements.

## Lab 3 - Add Inventory management
During a maintenance job, a mechanic often uses products like: tires, windscreen-wipers, oil, oil-filters, etcetera. There is currently no way to support this in Pitstop. In this lab you have to add the ability for a mechanic to add products that he or she uses during the execution of a maintenance-job. For every product used, the inventory must be updated and the price of the products must be added to the bill that is sent to the customer.

> Caution: this is a pretty big lab and it contains less detailed instructions than Lab 2. So take your time for this one!

In the context-map shown in the domain description on the Wiki, Inventory Management is shown (grayed out). Use this information in this assignment.

These are the requirements for this lab:
- The user must be able to add new products (update / delete not necessary).
- When adding a product, the user must be able to specify a name and a price of a product. A product id should be generated automatically.
- When a new product is added, a *ProductRegistered* event must be emitted to the message-broker.
- The *ProductRegistered* event must be ingested by the *WorkshopManagementEventHandler*. Registered products must be stored in the WorkshopManagement reference-data database.
- The *ProductRegistered* event must be ingested by the *InvoiceService*. Registered products (productId and name) must be stored in the Invoicing data database.
- A mechanic must be able to select a product (dropdown) and amount (text-box) for a particular *MaintenanceJob* (on the details page).
- When the selection is saved, a *UseProduct* command must be created that must be handled by the *WorkshopManagement* domain.
- Handling of the *UseProduct* command must produce a *ProductUsed* event that must be added to the *WorkshopManagement* event-store. This is the structure of the event:
 ```JSON
   {
      "messageId": "C0EAA76D-D566-41F8-B747-3D15C1F58996",
      "messageType": "ProductUsed",
      "maintenanceJobId": "0EC3A1DA-BDB9-4090-A76A-217D4474A4EA",
      "productId" : "C21042C8-D87A-4640-AE27-6C83F100347A",
      "amount": 2
   }
 ```
- The *ProductUsed* event must be published to the message-broker.
- The *ProductUsed* event must be handled by the *Invoicing* domain. This must add the used product to the maintenance-job.
- The *Invoicing* domain must add the products and price to the invoice when created.

> We will ignore updating the stock-amount of a product in this lab. For simplicity, we just assume there's an unlimited supply of products available in the inventory. Maybe you can implement a stock-amount in the *Inventory* domain (and updating this using *ProductUsed* events) as a bonus exercise.

This is a sequence diagram explaining the interaction between the different components involved:

![](img/inventory-management.png)

To fulfill these requirements, execute the following steps:

### Step 3.1: Create the *InventoryManagementAPI*

> For this step you can look at the existing *CustomerManagementAPI* for inspiration.

1. Add an *InventoryManagementAPI* project (ASP.NET WebAPI) to the solution that can be used to manage products.
2. Implement a POST operation on the API controller for registering a new product.
3. Implement data-access so the service can store products in a separate SQL Server database named *InventoryManagement*.
4. Expand the API controller so it uses a *RabbitMQMessagePublisher* (injected using standard DI) for publishing a *ProductRegistered* event. This is an example of the event:
   ```JSON
   {
      "messageId": "2DEF89EF-4403-4451-8661-A869258B301B",
      "messageType": "ProductRegistered",
      "productId" : "C21042C8-D87A-4640-AE27-6C83F100347A",
      "name": "All weather tire",
      "price": 85.0
   }
   ```
5. Test the functionality of registering a new product. Call the API directly and check whether the product is stored in the database and a *ProductRegistered* command is published to the message-broker.

### Step 3.2: Create the *InventoryManagement* UI module

> For this step you can look at the existing *CustomerManagement* module in the *WebApp*.

1. Add a simple screen in the *WebApp* that can be used to add products (hint: copy paste from existing pages in CustomerManagement module for example).
2. Create an HTTP client for calling the *InventoryManagementAPI*, inject it into to controller (using standard DI) and call it to register a product.
3. Test the functionality of registering a new product using the new page. Check whether the product is stored in the database and a *ProductRegistered* event is published to the message-broker.

### Step 3.3: Handle product-registration support to the *WorkshopManagement* domain

1. Expand the *WorkshopManagementEventHandler* so it ingests *ProductRegistered* events.
2. Add an event-handler that will store the registered product's information in the reference-data database (see the *CustomerRegistered* handler for inspiration).

### Step 3.4: Add product-selection to *WorkshopManagement* domain

1. Expand the *RefDataController* in the *WorkshopManagementAPI* so it can deliver a list of available products.
2. Expand the *MaintenanceJobDetails* page in the *WorkshopManagement* module in the *WebApp*:
   - Allow the user to select a product and an amount.
   - Allow the user to save the changes (or cancel without saving the changes).
   - Send a *UseProduct* command to the *WorkshopManagementAPI*. This is an example of the command:
   ```JSON
   {
      "messageId": "14F2E22C-FFC8-4079-A711-2DA52B755800",
      "messageType": "UseProduct",
      "maintenanceJobId": "0EC3A1DA-BDB9-4090-A76A-217D4474A4EA",
      "productId" : "C21042C8-D87A-4640-AE27-6C83F100347A",
      "price": 85.0,
      "amount": 2
   }
   ```
3. Add a controller method and a *UseProductCommandHandler* to the *WorkshopManagementAPI* that will handle the *UseProductCommand* (look at the existing controller methods and command-handlers for inspiration).
   - Make sure the new command-handler is registered in the *CommandHandlersDIRegistration* class!
4. Expand the *WorkshopPlanning* and *MaintenanceJob* entities in the *WorkshopManagement* domain so they can handle the *UseProduct* command. This command should result in a *ProductUsed* event (that will be automatically stored in the event-store). This is an example of the event:
   ```JSON
   {
      "messageId": "C0CB1C09-2E5C-4E13-A600-DB8CFA53B5CD",
      "messageType": "ProductUsed",
      "maintenanceJobId": "0EC3A1DA-BDB9-4090-A76A-217D4474A4EA",
      "productId" : "C21042C8-D87A-4640-AE27-6C83F100347A",
      "price": 85.0,
      "amount": 2
   }
   ```
5. Expand the *WorkshopManagementAPI* so that products used for a *MaintenanceJob* are returned when retrieving the details of this *MaintenanceJob*.
6. Expand the *MaintenanceJobDetails* page in the *WorkshopManagement* module in the *WebApp* so that the products that were used for a *MaintenanceJob* are shown.
7. Expand the *UseProductCommandHandler* so it uses the message-publisher (injected using standard DI) to publish a *ProductUsed* event to the message-broker.
8. Test the functionality to see whether or not it works correctly.

### Step 3.5: Handle product-registration and -usage in the *Invoicing* domain

1. Expand the *InvoiceService* so it ingests *ProductRegistered* and *ProductUsed* events.
2. Add a *ProductRegistered* event-handler that will store the registered product's information (only productId and name) in the database.
3. Add a *ProductUsed* event-handler that will store the used product's information (productId, amount and price) with the *MaintenanceJob* specified in the event in the database.
4. Expand the generation of the invoice so that:
   - The name, amount and total price of the used products are shown on the generated invoice (1 line per used product).
   - The price of the used products is added to the total price.
5. Because you created the event handlers for *ProductRegistered* and *ProductUsed* in the *InvoiceService* last, you will probably have a mismatch between the list of products in the *InventoryManagement* database and the *Invoicing* database. Fix this mismatch. There are two appproaches (choose one):
   - Empty all the databases and start over with registering new products. This is fine for the workshop (and the quickest solution), but never a good solution in production!
   - Replay all the *ProductRegistered* and *ProductUsed* events that were sent before by publishing them to the *Invoicing* queue using the RabbitMQ management console. See the 'Testing the application' section in the repo's Wiki for instructions on how to do this. You can use the JSON examples of the events in this lab as templates for the message-body. CAUTION: In the referenced description, a message is published to the *Pitstop* exchange. For your scenario, make sure you publish the events directly to the *Invoicing* queue. Try to answer for yourself why this is important.
6. Test the functionality to see whether or not it works correctly.

### Step 3.6: Run InventoryManagementAPI in docker container

As a bonus step, I will leave it entirely up to you to run the *InventoryManagementAPI* in a docker container as part of a docker-compose setup (see [Lab 2, step 2.4 - 2.6](#step-24-create-docker-image) for instructions). Use `pitstop/inventorymanagementapi:1.0` as tag for the container image.


text:
#Some Simple Web Scrapers

All in ruby, some useful to me, none very complicated. Using a few different gems - open-uri, crack, nokogiri, rest-client. gem install (whichever is required) if you are getting an error when running one of these.

If you need help automating a web task, like if you are copying and pasting from the web regularly, message me and we can figure out a way to save you some mindless tedium. None of these scrapers is likely to work for your particular task, but they are decent real-world examples.

Also, check out the [Bastard's Book of Ruby][bastard] - code samples, walkthroughs, and strong motivating stories for learning to wrassle data.

[bastard]: http://ruby.bastardsbook.com/chapters/web-scraping/

repository: rrcobb/scrapers

repo_name: rrcobb/scrapers


text:
# Agents: agent-based modeling framework in Julia

[![](https://img.shields.io/badge/Agents.jl-v1.1.7-blue.svg)](https://github.com/kavir1698/Agents.jl)
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://kavir1698.github.io/Agents.jl/stable)
[![](https://img.shields.io/badge/docs-latest-blue.svg)](https://kavir1698.github.io/Agents.jl/dev)
[![Build Status](https://travis-ci.org/kavir1698/Agents.jl.svg?branch=master)](https://travis-ci.org/kavir1698/Agents.jl)

Agents.jl is a [Julia](https://julialang.org/) framework for agent-based modeling (ABM). It provides a structure and components for quickly implementing agent-based models, run them in batch, collect data, and visualize them. To that end, it provides the following functionalities:

* Default grids to run the simulation, including simple or toroidal 1D grids, simple or toroidal regular rectangular and triangular 2D grids, and simple or toroidal regular cubic 3D grids with von Neumann or Moore neighborhoods. More space structure are to be implemented include arbitrary random networks.
* Running the simulations in parallel on multiple cores.
* Automatic data collection in a `DataFrame` at desired intervals.
* Exploring the simulation results interactively in [Data Voyager 2](https://github.com/vega/voyager).
* Batch running and batch data collection
* Visualize agent distributions on grids

Julia is a language that is especially suitable for ABMs, because a) [it runs fast](https://julialang.org/benchmarks/), b) it is easy to express your ideas in and quick to write, and c) it has rich and easy-to-use packages for data analysis.

Agents.jl is lightweight and modular. It has a short learning curve, and allows one to extend its capabilities and express complicated modeling scenarios. Agents.jl is inspired by [Mesa](https://github.com/projectmesa/mesa) framework for Python.

## Installation

Install using the following command inside Julia:

```julia
]add Agents
```

It is compatible with Julia 0.7+.

For a tutorial, read the docs: [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://kavir1698.github.io/Agents.jl/stable)

gha_license_id: NOASSERTION


text:
# Shycube

A simple example on how to use the AnimatorController for driving a Finite State Machine (for AI) in Unity
https://sizzlinghotsingularities.blogspot.com/2018/11/unity-animator-finite-state-machines.html


text:
# bank-admin-backend

## Backend Coding Challenge

Create a REST service that can fetch bank details, using the data given in the API’s query parameters. The data obtained is available at: **https://github.com/snarayanank2/indian_banks**. The services are written using Django and the application is hosted on Heroku. PostgreSQL is used for the backend database and since the free-tier of Heroku has a limit of 10k rows, **_clever-cloud.com_** was used to host the database. Postman was used for testing the APIs and for generating the curl scripts.

The usecases of the application:

1. Autocomplete API to return possible matches based on the branch name ordered by IFSC code (ascending order) with limit and offset.
    - Endpoint: /api/branches/autocomplete?q=<>
    - Example: /api/branches/autocomplete?q=RTGS&limit=3&offset=0

2. Search API to return possible matches across all columns and all rows, ordered by IFSC code (ascending order) with limit and offset.

    - Endpoint: /api/branches?q=<>
    - Example: /api/branches?q=Bangalore&limit=4&offset=0

## API Urls

Autocomplete API
> https://aanandhivb-1.herokuapp.com/api/branches/autocomplete?q=ERNAKULAM&limit=3&offset=2

Search API
> https://aanandhivb-1.herokuapp.com/api/branches?q=TRIVANDRUM&limit=5&offset=1

## Curl Scripts

Autocomplete API
> curl --location --request GET 'https://aanandhivb-1.herokuapp.com/api/branches/autocomplete?q=ERNAKULAM&limit=3&offset=2'

Search API
> curl --location --request GET 'https://aanandhivb-1.herokuapp.com/api/branches?q=TRIVANDRUM&limit=5&offset=1'

## Time Taken

Total time taken (including coding, testing, deploying)  - 1 hour 30 minutes

repository: AanandhiVB/bank-admin-backend

branch_name: refs/heads/main

repo_name: AanandhiVB/bank-admin-backend