@coderkearns/reactivity
Advanced tools
| import ReactiveValue from "./value" | ||
| import ReactiveArray from "./array" | ||
| import ReactiveObject from "./object" | ||
| export function makeSubscription(item) { | ||
| if (typeof item === "object") { | ||
| if (Array.isArray(item)) { | ||
| return new ReactiveArray(item) | ||
| } else { | ||
| return new ReactiveObject(item) | ||
| } | ||
| } | ||
| return new ReactiveValue(item) | ||
| } |
+79
-39
@@ -29,18 +29,15 @@ var __defProp = Object.defineProperty; | ||
| // lib/value.js | ||
| var ReactiveValue = class extends Subscription { | ||
| constructor(initialValue) { | ||
| super(); | ||
| this._value = initialValue; | ||
| // lib/subscription.js | ||
| var Subscription = class { | ||
| constructor() { | ||
| this._subscribers = []; | ||
| } | ||
| get() { | ||
| return this._value; | ||
| subscribe(subscriber) { | ||
| this._subscribers.push(subscriber); | ||
| } | ||
| set(value) { | ||
| this._value = value; | ||
| this.publish(this._value); | ||
| publish(...values) { | ||
| for (let subscriber of this._subscribers) { | ||
| subscriber(...values); | ||
| } | ||
| } | ||
| static() { | ||
| return this._value; | ||
| } | ||
| }; | ||
@@ -50,13 +47,29 @@ | ||
| var ReactiveArray = class extends Subscription { | ||
| constructor(initialArray) { | ||
| constructor(initialArray = []) { | ||
| super(); | ||
| this._internal = []; | ||
| for (const item of initialArray) { | ||
| this._internal.push(Subscription.from(item)); | ||
| for (const value of initialArray) { | ||
| this.push(value); | ||
| } | ||
| } | ||
| _makeSubscriberFunc(key) { | ||
| return (value, oldKey = null) => { | ||
| this.publish(value, oldKey ? `${key}.${oldKey}` : `${key}`); | ||
| }; | ||
| } | ||
| _makeAndSubscribe(value, key) { | ||
| const item = makeSubscription(value); | ||
| item.subscribe(this._makeSubscriberFunc(key)); | ||
| return item; | ||
| } | ||
| static() { | ||
| return this._internal.map((item) => item.static()); | ||
| } | ||
| // TODO: implement all the stuff | ||
| /* Array methods */ | ||
| push(value) { | ||
| const key = this._internal.length; | ||
| const item = this._makeAndSubscribe(item, key); | ||
| this._internal.push(item); | ||
| this.publish(value, `${key}`); | ||
| } | ||
| }; | ||
@@ -66,9 +79,19 @@ | ||
| var ReactiveObject = class extends Subscription { | ||
| constructor(initialObject) { | ||
| constructor(initialObject = {}) { | ||
| super(); | ||
| this._internal = {}; | ||
| for (const key in initialObject) { | ||
| this._internal[key] = Subscription.from(initialObject[key]); | ||
| this.set(key, initialObject[key]); | ||
| } | ||
| } | ||
| _makeSubscriberFunc(key) { | ||
| return (value, oldKey = null) => { | ||
| this.publish(value, oldKey ? `${key}.${oldKey}` : key); | ||
| }; | ||
| } | ||
| _makeAndSubscribe(value, key) { | ||
| const item = makeSubscription(value); | ||
| item.subscribe(this._makeSubscriberFunc(key)); | ||
| return item; | ||
| } | ||
| static() { | ||
@@ -80,28 +103,45 @@ const _static = {}; | ||
| } | ||
| // TODO: implement all the stuff | ||
| /* Object methods */ | ||
| set(key, value) { | ||
| if (this._internal[key] !== void 0) { | ||
| this._internal[key].set(value); | ||
| } else { | ||
| const item = this._makeAndSubscribe(value, key); | ||
| this._internal[key] = item; | ||
| this.publish(value, key); | ||
| } | ||
| } | ||
| get(key) { | ||
| return this._internal[key]; | ||
| } | ||
| }; | ||
| // lib/subscription.js | ||
| var Subscription = class { | ||
| constructor() { | ||
| this._subscribers = []; | ||
| // lib/shared.js | ||
| function makeSubscription(item) { | ||
| if (typeof item === "object") { | ||
| if (Array.isArray(item)) { | ||
| return new ReactiveArray(item); | ||
| } else { | ||
| return new ReactiveObject(item); | ||
| } | ||
| } | ||
| subscribe(subscriber) { | ||
| this._subscribers.push(subscriber); | ||
| return new ReactiveValue(item); | ||
| } | ||
| // lib/value.js | ||
| var ReactiveValue = class extends Subscription { | ||
| constructor(initialValue) { | ||
| super(); | ||
| this._value = initialValue; | ||
| } | ||
| publish(...values) { | ||
| for (let subscriber of this._subscribers) { | ||
| subscriber(...values); | ||
| } | ||
| get() { | ||
| return this._value; | ||
| } | ||
| static from(item) { | ||
| if (typeof item === "object") { | ||
| if (Array.isArray(item)) { | ||
| return new ReactiveArray(item); | ||
| } else { | ||
| return new ReactiveObject(item); | ||
| } | ||
| } | ||
| return new ReactiveValue(item); | ||
| set(value) { | ||
| this._value = value; | ||
| this.publish(this._value); | ||
| } | ||
| static() { | ||
| return this._value; | ||
| } | ||
| }; | ||
@@ -108,0 +148,0 @@ // Annotate the CommonJS export names for ESM import in node: |
+1
-1
@@ -1,2 +0,2 @@ | ||
| (()=>{var e=class extends r{constructor(t){super(),this._value=t}get(){return this._value}set(t){this._value=t,this.publish(this._value)}static(){return this._value}};var i=class extends r{constructor(t){super(),this._internal=[];for(let s of t)this._internal.push(r.from(s))}static(){return this._internal.map(t=>t.static())}};var o=class extends r{constructor(t){super(),this._internal={};for(let s in t)this._internal[s]=r.from(t[s])}static(){let t={};for(let s in this._internal)t[s]=this._internal[s].static()}};var r=class{constructor(){this._subscribers=[]}subscribe(t){this._subscribers.push(t)}publish(...t){for(let s of this._subscribers)s(...t)}static from(t){return typeof t=="object"?Array.isArray(t)?new i(t):new o(t):new e(t)}};})(); | ||
| (()=>{var e=class{constructor(){this._subscribers=[]}subscribe(t){this._subscribers.push(t)}publish(...t){for(let s of this._subscribers)s(...t)}};var n=class extends e{constructor(t=[]){super(),this._internal=[];for(let s of t)this.push(s)}_makeSubscriberFunc(t){return(s,r=null)=>{this.publish(s,r?`${t}.${r}`:`${t}`)}}_makeAndSubscribe(t,s){let r=c(t);return r.subscribe(this._makeSubscriberFunc(s)),r}static(){return this._internal.map(t=>t.static())}push(t){let s=this._internal.length,r=this._makeAndSubscribe(r,s);this._internal.push(r),this.publish(t,`${s}`)}};var u=class extends e{constructor(t={}){super(),this._internal={};for(let s in t)this.set(s,t[s])}_makeSubscriberFunc(t){return(s,r=null)=>{this.publish(s,r?`${t}.${r}`:t)}}_makeAndSubscribe(t,s){let r=c(t);return r.subscribe(this._makeSubscriberFunc(s)),r}static(){let t={};for(let s in this._internal)t[s]=this._internal[s].static()}set(t,s){if(this._internal[t]!==void 0)this._internal[t].set(s);else{let r=this._makeAndSubscribe(s,t);this._internal[t]=r,this.publish(s,t)}}get(t){return this._internal[t]}};function c(i){return typeof i=="object"?Array.isArray(i)?new n(i):new u(i):new o(i)}var o=class extends e{constructor(t){super(),this._value=t}get(){return this._value}set(t){this._value=t,this.publish(this._value)}static(){return this._value}};})(); | ||
| //# sourceMappingURL=index.js.map |
| { | ||
| "version": 3, | ||
| "sources": ["../lib/value.js", "../lib/array.js", "../lib/object.js", "../lib/subscription.js"], | ||
| "sourcesContent": ["import Subscription from \"./subscription\";\n\nexport default class ReactiveValue extends Subscription {\n constructor(initialValue) {\n super()\n this._value = initialValue\n }\n\n get() {\n return this._value\n }\n\n set(value) {\n this._value = value\n this.publish(this._value)\n }\n\n static() {\n return this._value\n }\n}\n", "import Subscription from \"./subscription\";\n\nexport default class ReactiveArray extends Subscription {\n constructor(initialArray) {\n super()\n\n this._internal = []\n\n for (const item of initialArray) {\n this._internal.push(Subscription.from(item))\n }\n }\n\n static() {\n return this._internal.map(item => item.static())\n }\n\n // TODO: implement all the stuff\n}\n", "import Subscription from \"./subscription\";\n\nexport default class ReactiveObject extends Subscription {\n constructor(initialObject) {\n super()\n\n this._internal = {}\n\n for (const key in initialObject) {\n this._internal[key] = Subscription.from(initialObject[key])\n }\n }\n\n static() {\n const _static = {}\n for (const key in this._internal) {\n _static[key] = this._internal[key].static()\n }\n }\n\n // TODO: implement all the stuff\n}\n", "import ReactiveValue from \"./value\"\nimport ReactiveArray from \"./array\"\nimport ReactiveObject from \"./object\"\n\nexport default class Subscription {\n constructor() {\n this._subscribers = []\n }\n\n subscribe(subscriber) {\n this._subscribers.push(subscriber)\n }\n\n publish(...values) {\n for (let subscriber of this._subscribers) {\n subscriber(...values)\n }\n }\n\n static from(item) {\n if (typeof item === \"object\") {\n if (Array.isArray(item)) {\n return new ReactiveArray(item)\n } else {\n return new ReactiveObject(item)\n }\n }\n\n return new ReactiveValue(item)\n }\n}\n"], | ||
| "mappings": "MAEA,IAAqBA,EAArB,cAA2CC,CAAa,CACpD,YAAYC,EAAc,CACtB,MAAM,EACN,KAAK,OAASA,CAClB,CAEA,KAAM,CACF,OAAO,KAAK,MAChB,CAEA,IAAIC,EAAO,CACP,KAAK,OAASA,EACd,KAAK,QAAQ,KAAK,MAAM,CAC5B,CAEA,QAAS,CACL,OAAO,KAAK,MAChB,CACJ,EClBA,IAAqBC,EAArB,cAA2CC,CAAa,CACpD,YAAYC,EAAc,CACtB,MAAM,EAEN,KAAK,UAAY,CAAC,EAElB,QAAWC,KAAQD,EACf,KAAK,UAAU,KAAKD,EAAa,KAAKE,CAAI,CAAC,CAEnD,CAEA,QAAS,CACL,OAAO,KAAK,UAAU,IAAIA,GAAQA,EAAK,OAAO,CAAC,CACnD,CAGJ,EChBA,IAAqBC,EAArB,cAA4CC,CAAa,CACrD,YAAYC,EAAe,CACvB,MAAM,EAEN,KAAK,UAAY,CAAC,EAElB,QAAWC,KAAOD,EACd,KAAK,UAAUC,CAAG,EAAIF,EAAa,KAAKC,EAAcC,CAAG,CAAC,CAElE,CAEA,QAAS,CACL,IAAMC,EAAU,CAAC,EACjB,QAAWD,KAAO,KAAK,UACnBC,EAAQD,CAAG,EAAI,KAAK,UAAUA,CAAG,EAAE,OAAO,CAElD,CAGJ,ECjBA,IAAqBE,EAArB,KAAkC,CAC9B,aAAc,CACV,KAAK,aAAe,CAAC,CACzB,CAEA,UAAUC,EAAY,CAClB,KAAK,aAAa,KAAKA,CAAU,CACrC,CAEA,WAAWC,EAAQ,CACf,QAASD,KAAc,KAAK,aACxBA,EAAW,GAAGC,CAAM,CAE5B,CAEA,OAAO,KAAKC,EAAM,CACd,OAAI,OAAOA,GAAS,SACZ,MAAM,QAAQA,CAAI,EACX,IAAIC,EAAcD,CAAI,EAEtB,IAAIE,EAAeF,CAAI,EAI/B,IAAIG,EAAcH,CAAI,CACjC,CACJ", | ||
| "names": ["ReactiveValue", "Subscription", "initialValue", "value", "ReactiveArray", "Subscription", "initialArray", "item", "ReactiveObject", "Subscription", "initialObject", "key", "_static", "Subscription", "subscriber", "values", "item", "ReactiveArray", "ReactiveObject", "ReactiveValue"] | ||
| "sources": ["../lib/subscription.js", "../lib/array.js", "../lib/object.js", "../lib/shared.js", "../lib/value.js"], | ||
| "sourcesContent": ["export default class Subscription {\n constructor() {\n this._subscribers = []\n }\n\n subscribe(subscriber) {\n this._subscribers.push(subscriber)\n }\n\n publish(...values) {\n for (let subscriber of this._subscribers) {\n subscriber(...values)\n }\n }\n}\n", "import Subscription from \"./subscription\";\nimport { makeSubscription } from \"./shared\";\n\nexport default class ReactiveArray extends Subscription {\n constructor(initialArray = []) {\n super()\n\n this._internal = []\n\n for (const value of initialArray) {\n this.push(value)\n }\n }\n\n _makeSubscriberFunc(key) {\n return (value, oldKey = null) => {\n this.publish(value, oldKey ? `${key}.${oldKey}` : `${key}`)\n }\n }\n\n _makeAndSubscribe(value, key) {\n const item = makeSubscription(value)\n item.subscribe(this._makeSubscriberFunc(key))\n return item\n }\n\n static() {\n return this._internal.map(item => item.static())\n }\n\n /* Array methods */\n push(value) {\n const key = this._internal.length\n const item = this._makeAndSubscribe(item, key)\n this._internal.push(item)\n this.publish(value, `${key}`)\n }\n}\n", "import Subscription from \"./subscription\";\nimport { makeSubscription } from \"./shared\";\n\nexport default class ReactiveObject extends Subscription {\n constructor(initialObject = {}) {\n super()\n\n this._internal = {}\n\n for (const key in initialObject) {\n this.set(key, initialObject[key])\n }\n }\n\n _makeSubscriberFunc(key) {\n return (value, oldKey = null) => {\n this.publish(value, oldKey ? `${key}.${oldKey}` : key)\n }\n }\n\n _makeAndSubscribe(value, key) {\n const item = makeSubscription(value)\n item.subscribe(this._makeSubscriberFunc(key))\n return item\n }\n\n static() {\n const _static = {}\n for (const key in this._internal) {\n _static[key] = this._internal[key].static()\n }\n }\n\n /* Object methods */\n set(key, value) {\n if (this._internal[key] !== undefined) {\n this._internal[key].set(value)\n } else {\n const item = this._makeAndSubscribe(value, key)\n this._internal[key] = item\n this.publish(value, key)\n }\n }\n\n get(key) {\n return this._internal[key]\n }\n}\n", "import ReactiveValue from \"./value\"\nimport ReactiveArray from \"./array\"\nimport ReactiveObject from \"./object\"\n\nexport function makeSubscription(item) {\n if (typeof item === \"object\") {\n if (Array.isArray(item)) {\n return new ReactiveArray(item)\n } else {\n return new ReactiveObject(item)\n }\n }\n\n return new ReactiveValue(item)\n}\n", "import Subscription from \"./subscription\";\nimport { makeSubscription } from \"./shared\";\n\nexport default class ReactiveValue extends Subscription {\n constructor(initialValue) {\n super()\n this._value = initialValue\n }\n\n get() {\n return this._value\n }\n\n set(value) {\n this._value = value\n this.publish(this._value)\n }\n\n static() {\n return this._value\n }\n}\n"], | ||
| "mappings": "MAAA,IAAqBA,EAArB,KAAkC,CAC9B,aAAc,CACV,KAAK,aAAe,CAAC,CACzB,CAEA,UAAUC,EAAY,CAClB,KAAK,aAAa,KAAKA,CAAU,CACrC,CAEA,WAAWC,EAAQ,CACf,QAASD,KAAc,KAAK,aACxBA,EAAW,GAAGC,CAAM,CAE5B,CACJ,ECXA,IAAqBC,EAArB,cAA2CC,CAAa,CACpD,YAAYC,EAAe,CAAC,EAAG,CAC3B,MAAM,EAEN,KAAK,UAAY,CAAC,EAElB,QAAWC,KAASD,EAChB,KAAK,KAAKC,CAAK,CAEvB,CAEA,oBAAoBC,EAAK,CACrB,MAAO,CAACD,EAAOE,EAAS,OAAS,CAC7B,KAAK,QAAQF,EAAOE,EAAS,GAAGD,KAAOC,IAAW,GAAGD,GAAK,CAC9D,CACJ,CAEA,kBAAkBD,EAAOC,EAAK,CAC1B,IAAME,EAAOC,EAAiBJ,CAAK,EACnC,OAAAG,EAAK,UAAU,KAAK,oBAAoBF,CAAG,CAAC,EACrCE,CACX,CAEA,QAAS,CACL,OAAO,KAAK,UAAU,IAAIA,GAAQA,EAAK,OAAO,CAAC,CACnD,CAGA,KAAKH,EAAO,CACR,IAAMC,EAAM,KAAK,UAAU,OACrBE,EAAO,KAAK,kBAAkBA,EAAMF,CAAG,EAC7C,KAAK,UAAU,KAAKE,CAAI,EACxB,KAAK,QAAQH,EAAO,GAAGC,GAAK,CAChC,CACJ,EClCA,IAAqBI,EAArB,cAA4CC,CAAa,CACrD,YAAYC,EAAgB,CAAC,EAAG,CAC5B,MAAM,EAEN,KAAK,UAAY,CAAC,EAElB,QAAWC,KAAOD,EACd,KAAK,IAAIC,EAAKD,EAAcC,CAAG,CAAC,CAExC,CAEA,oBAAoBA,EAAK,CACrB,MAAO,CAACC,EAAOC,EAAS,OAAS,CAC7B,KAAK,QAAQD,EAAOC,EAAS,GAAGF,KAAOE,IAAWF,CAAG,CACzD,CACJ,CAEA,kBAAkBC,EAAOD,EAAK,CAC1B,IAAMG,EAAOC,EAAiBH,CAAK,EACnC,OAAAE,EAAK,UAAU,KAAK,oBAAoBH,CAAG,CAAC,EACrCG,CACX,CAEA,QAAS,CACL,IAAME,EAAU,CAAC,EACjB,QAAWL,KAAO,KAAK,UACnBK,EAAQL,CAAG,EAAI,KAAK,UAAUA,CAAG,EAAE,OAAO,CAElD,CAGA,IAAIA,EAAKC,EAAO,CACZ,GAAI,KAAK,UAAUD,CAAG,IAAM,OACxB,KAAK,UAAUA,CAAG,EAAE,IAAIC,CAAK,MAC1B,CACH,IAAME,EAAO,KAAK,kBAAkBF,EAAOD,CAAG,EAC9C,KAAK,UAAUA,CAAG,EAAIG,EACtB,KAAK,QAAQF,EAAOD,CAAG,EAE/B,CAEA,IAAIA,EAAK,CACL,OAAO,KAAK,UAAUA,CAAG,CAC7B,CACJ,EC3CO,SAASM,EAAiBC,EAAM,CACnC,OAAI,OAAOA,GAAS,SACZ,MAAM,QAAQA,CAAI,EACX,IAAIC,EAAcD,CAAI,EAEtB,IAAIE,EAAeF,CAAI,EAI/B,IAAIG,EAAcH,CAAI,CACjC,CCXA,IAAqBI,EAArB,cAA2CC,CAAa,CACpD,YAAYC,EAAc,CACtB,MAAM,EACN,KAAK,OAASA,CAClB,CAEA,KAAM,CACF,OAAO,KAAK,MAChB,CAEA,IAAIC,EAAO,CACP,KAAK,OAASA,EACd,KAAK,QAAQ,KAAK,MAAM,CAC5B,CAEA,QAAS,CACL,OAAO,KAAK,MAChB,CACJ", | ||
| "names": ["Subscription", "subscriber", "values", "ReactiveArray", "Subscription", "initialArray", "value", "key", "oldKey", "item", "makeSubscription", "ReactiveObject", "Subscription", "initialObject", "key", "value", "oldKey", "item", "makeSubscription", "_static", "makeSubscription", "item", "ReactiveArray", "ReactiveObject", "ReactiveValue", "ReactiveValue", "Subscription", "initialValue", "value"] | ||
| } |
+23
-4
| import Subscription from "./subscription"; | ||
| import { makeSubscription } from "./shared"; | ||
| export default class ReactiveArray extends Subscription { | ||
| constructor(initialArray) { | ||
| constructor(initialArray = []) { | ||
| super() | ||
@@ -9,7 +10,19 @@ | ||
| for (const item of initialArray) { | ||
| this._internal.push(Subscription.from(item)) | ||
| for (const value of initialArray) { | ||
| this.push(value) | ||
| } | ||
| } | ||
| _makeSubscriberFunc(key) { | ||
| return (value, oldKey = null) => { | ||
| this.publish(value, oldKey ? `${key}.${oldKey}` : `${key}`) | ||
| } | ||
| } | ||
| _makeAndSubscribe(value, key) { | ||
| const item = makeSubscription(value) | ||
| item.subscribe(this._makeSubscriberFunc(key)) | ||
| return item | ||
| } | ||
| static() { | ||
@@ -19,3 +32,9 @@ return this._internal.map(item => item.static()) | ||
| // TODO: implement all the stuff | ||
| /* Array methods */ | ||
| push(value) { | ||
| const key = this._internal.length | ||
| const item = this._makeAndSubscribe(item, key) | ||
| this._internal.push(item) | ||
| this.publish(value, `${key}`) | ||
| } | ||
| } |
+1
-1
@@ -1,4 +0,4 @@ | ||
| export { default as Subscription } from "./subscription"; | ||
| export { default as Subscription } from "./subscription" | ||
| export { default as ReactiveValue } from "./value" | ||
| export { default as ReactiveArray } from "./array" | ||
| export { default as ReactiveObject } from "./object" |
+29
-3
| import Subscription from "./subscription"; | ||
| import { makeSubscription } from "./shared"; | ||
| export default class ReactiveObject extends Subscription { | ||
| constructor(initialObject) { | ||
| constructor(initialObject = {}) { | ||
| super() | ||
@@ -10,6 +11,18 @@ | ||
| for (const key in initialObject) { | ||
| this._internal[key] = Subscription.from(initialObject[key]) | ||
| this.set(key, initialObject[key]) | ||
| } | ||
| } | ||
| _makeSubscriberFunc(key) { | ||
| return (value, oldKey = null) => { | ||
| this.publish(value, oldKey ? `${key}.${oldKey}` : key) | ||
| } | ||
| } | ||
| _makeAndSubscribe(value, key) { | ||
| const item = makeSubscription(value) | ||
| item.subscribe(this._makeSubscriberFunc(key)) | ||
| return item | ||
| } | ||
| static() { | ||
@@ -22,3 +35,16 @@ const _static = {} | ||
| // TODO: implement all the stuff | ||
| /* Object methods */ | ||
| set(key, value) { | ||
| if (this._internal[key] !== undefined) { | ||
| this._internal[key].set(value) | ||
| } else { | ||
| const item = this._makeAndSubscribe(value, key) | ||
| this._internal[key] = item | ||
| this.publish(value, key) | ||
| } | ||
| } | ||
| get(key) { | ||
| return this._internal[key] | ||
| } | ||
| } |
+0
-16
@@ -1,5 +0,1 @@ | ||
| import ReactiveValue from "./value" | ||
| import ReactiveArray from "./array" | ||
| import ReactiveObject from "./object" | ||
| export default class Subscription { | ||
@@ -19,14 +15,2 @@ constructor() { | ||
| } | ||
| static from(item) { | ||
| if (typeof item === "object") { | ||
| if (Array.isArray(item)) { | ||
| return new ReactiveArray(item) | ||
| } else { | ||
| return new ReactiveObject(item) | ||
| } | ||
| } | ||
| return new ReactiveValue(item) | ||
| } | ||
| } |
+1
-0
| import Subscription from "./subscription"; | ||
| import { makeSubscription } from "./shared"; | ||
@@ -3,0 +4,0 @@ export default class ReactiveValue extends Subscription { |
+1
-1
| { | ||
| "name": "@coderkearns/reactivity", | ||
| "version": "1.0.3", | ||
| "version": "1.2.0", | ||
| "description": "My personal reactivity library", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
+1
-1
@@ -5,3 +5,3 @@ # reactivity | ||
| TODO: more description lol | ||
| Heavily based on the **Observer** (also known as **Subscription**) design pattern. | ||
@@ -8,0 +8,0 @@ ## Getting Started |
16999
42.9%12
9.09%270
44.39%