@everymatrix/lottery-program-wof 1.13.9 → 1.13.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everymatrix/lottery-program-wof",
3
- "version": "1.13.9",
3
+ "version": "1.13.11",
4
4
  "main": "dist/lottery-program-wof.js",
5
5
  "svelte": "src/index.ts",
6
6
  "scripts": {
@@ -9,14 +9,17 @@
9
9
  "build:watch": "cross-env NODE_ENV=\"production\" && rollup -c -w",
10
10
  "dev": "cross-env NODE_ENV=\"development\" rollup -c -w",
11
11
  "validate": "svelte-check",
12
- "test": "echo"
12
+ "test": "jest"
13
13
  },
14
14
  "devDependencies": {
15
+ "@babel/preset-typescript": "^7.22.5",
15
16
  "@rollup/plugin-babel": "^5.3.0",
16
17
  "@rollup/plugin-commonjs": "^16.0.0",
17
18
  "@rollup/plugin-node-resolve": "^10.0.0",
18
19
  "@rollup/plugin-typescript": "^6.0.0",
19
20
  "@tsconfig/svelte": "^1.0.0",
21
+ "@types/jest": "^29.5.2",
22
+ "jest": "^29.5.0",
20
23
  "rollup": "^2.3.4",
21
24
  "rollup-plugin-dev-server": "^0.4.3",
22
25
  "rollup-plugin-livereload": "^2.0.0",
@@ -36,5 +39,5 @@
36
39
  "publishConfig": {
37
40
  "access": "public"
38
41
  },
39
- "gitHead": "92bb59e79a581b4130638d57db5ee581120ac2ba"
42
+ "gitHead": "402517f6a835d8e0628228df02acf7f95ddd7a47"
40
43
  }
@@ -12,20 +12,36 @@
12
12
 
13
13
  // types
14
14
  import { Lang } from './types';
15
- import type { LotteryProgram } from './api';
16
15
  import { api } from './business';
17
16
 
18
17
  import { _postMessage } from './message';
19
- import type { LotteryProgramForPlayer } from './types.business';
20
- import { classWithPart } from './util';
18
+ import { CurrentInfo, LotteryProgramForPlayer } from './types.business';
19
+ import { setClientStyling, setClientStylingURL, setTranslationUrl } from './widget';
21
20
 
22
21
  // properties
23
22
  export let lang: Lang = Lang.en
24
23
  export let endpoint: string = ''
25
24
  export let session: string = ''
26
-
27
- export let spinduration: string = '3'
28
- export let spinrotation: string = '3'
25
+ export let clientstyling: string = ''
26
+ export let clientstylingurl: string = ''
27
+ export let translationurl: string = ''
28
+ export let loginevent: string = ''
29
+ export let loginurl: string = ''
30
+ export let currentinfo: CurrentInfo = CurrentInfo.RemainingTimes
31
+ export let giftimagesrc: string = ''
32
+ export let isshowhistory: string = 'true'
33
+
34
+ let rootContainer: HTMLElement
35
+ $: clientstyling && rootContainer && setClientStyling(rootContainer, clientstyling);
36
+ $: clientstylingurl && rootContainer && setClientStylingURL(clientstylingurl, (_clientstyling) => clientstyling = _clientstyling);
37
+ $: translationurl && setTranslationUrl(translationurl);
38
+
39
+ $: commonProps = {
40
+ endpoint,
41
+ lang,
42
+ session,
43
+ clientstyling,
44
+ }
29
45
 
30
46
  let isMounted = false
31
47
  $: isMounted && init()
@@ -36,11 +52,17 @@
36
52
 
37
53
  setLocaleWhenInit()
38
54
 
39
- let lotteryProgramsForPlayer: LotteryProgramForPlayer[] = []
40
- let lotteryProgram: LotteryProgram;
55
+ let bonuses: LotteryProgramForPlayer[] = []
41
56
  let loading: boolean = true;
42
57
 
58
+ $: hasSession = session && session !== 'false'
59
+
43
60
  const init = async () => {
61
+ loading = true
62
+ if(!hasSession) {
63
+ loginAction(loginevent, loginurl)
64
+ return;
65
+ }
44
66
 
45
67
  if(!isMounted || !lang || !session || !endpoint) return;
46
68
 
@@ -50,8 +72,18 @@
50
72
  }
51
73
 
52
74
  const fetcher = async () => {
53
- lotteryProgramsForPlayer = await api.lotteries(endpoint, session)
54
- _postMessage({type: 'wof-private-message-lotteryProgramsForPlayer', lotteryProgramsForPlayer })
75
+ bonuses = await api.lotteries(endpoint, session)
76
+ _postMessage({type: 'wof-private-bonuses', bonuses })
77
+ }
78
+
79
+ const loginAction = (loginevent, loginurl) => {
80
+ if (loginevent) {
81
+ window.postMessage({ type: loginevent, transition: 'Login' }, window.location.href);
82
+ }
83
+
84
+ if (loginurl) {
85
+ window.location = loginurl;
86
+ }
55
87
  }
56
88
 
57
89
  const setLangReactive = () => {
@@ -65,25 +97,24 @@
65
97
 
66
98
  </script>
67
99
 
68
- <div {...classWithPart("Root")}>
69
-
70
- <lottery-program-wof-private-tabs {lang}>
100
+ <div class="WofContainer" bind:this={rootContainer}>
101
+ <lottery-program-wof-private-tabs {...commonProps} {isshowhistory}>
71
102
  <div slot="tab-Program">
72
- <div {...classWithPart('CommonContainer')}>
103
+ <div class="CommonContainer">
73
104
  {#if loading}
74
105
  <wof-loader />
75
106
  {:else}
76
- {#if lotteryProgramsForPlayer.length}
77
- {#each lotteryProgramsForPlayer as _l}
78
- <lottery-program-wof-private-item {...{
79
- lang,
80
- endpoint,
81
- session,
82
- lotteryprogramforplayer: JSON.stringify(_l)
107
+ {#if bonuses.length}
108
+ {#each bonuses as _l}
109
+ <lottery-program-wof-private-item {...{
110
+ ...commonProps,
111
+ id: _l.program.id,
112
+ currentinfo,
113
+ giftimagesrc,
83
114
  }} />
84
115
  {/each}
85
116
  {:else}
86
- <div {...classWithPart("NoContent")}>
117
+ <div class="NoContent">
87
118
  <p>{$_('wof.NoContent')}</p>
88
119
  </div>
89
120
  {/if}
@@ -91,12 +122,7 @@
91
122
  </div>
92
123
  </div>
93
124
  <div slot="tab-History">
94
- <lottery-program-wof-private-outcomes
95
- {...{
96
- endpoint, session,
97
- partitions: lotteryProgram?.wheelOfFortune.partitions ? JSON.stringify(lotteryProgram?.wheelOfFortune.partitions) : '[]',
98
- }}
99
- />
125
+ <lottery-program-wof-private-outcomes {...commonProps} />
100
126
  </div>
101
127
  </lottery-program-wof-private-tabs>
102
128
  </div>
@@ -122,7 +148,7 @@
122
148
  box-sizing: border-box;
123
149
  }
124
150
 
125
- .Root {
151
+ .WofContainer {
126
152
  display: flex;
127
153
  align-items: center;
128
154
  flex-direction: column;
@@ -0,0 +1,34 @@
1
+ import { getColorSchema } from "./business.dom"
2
+ import { partitions3, partitions2, partitions1 } from "./themes.partitions"
3
+
4
+ const partitionsList = {
5
+ partitions1,
6
+ partitions2,
7
+ partitions3,
8
+ }
9
+
10
+ const maxLength = 12
11
+
12
+ const tester = (iLength, partitions) => {
13
+
14
+ const color = (i) => getColorSchema(i, iLength, partitions.colorSchema)[0].color
15
+
16
+ const colors = []
17
+
18
+ for(let i = 0; i < iLength; i++){
19
+ colors.push(color(i))
20
+ }
21
+
22
+ expect(colors[0]).not.toEqual((colors[iLength - 1]))
23
+ }
24
+
25
+ describe("check if first color is not equal last color", () => {
26
+ Object.keys(partitionsList).map(key => {
27
+ const partitions = partitionsList[key]
28
+ describe("for " + key, () => {
29
+ for(let length = 2; length < maxLength; length ++){
30
+ test('length ' + length, () => tester(length, partitions))
31
+ }
32
+ })
33
+ })
34
+ })
@@ -6,7 +6,16 @@ export const getPropsOfBackgroundCircle = (radius, rRingOuter, rRingInner) => ({
6
6
  'stroke-width': `${(rRingOuter - rRingInner) * 2}px`
7
7
  })
8
8
 
9
-
9
+ // color schema length must be greater than 2
10
10
  export const getColorSchema = (index, length, colorSchema) => {
11
- return colorSchema[index % Math.ceil(length / 2)]
11
+ if(
12
+ length > colorSchema.length &&
13
+ length % colorSchema.length === 1 &&
14
+ index === length - 1
15
+ ){
16
+ return colorSchema[1 % colorSchema.length]
17
+ }
18
+
19
+ return colorSchema[index % colorSchema.length]
20
+
12
21
  }
package/src/business.ts CHANGED
@@ -1,11 +1,10 @@
1
1
  import type { WheelOfFortunePartition } from './api';
2
2
  import { findDeg } from './calc';
3
3
  import { getStatePropsForSpin } from './css.state';
4
- import fakeDraw from './fakeDraw';
5
- import fakeResult from './fakeResult';
6
4
  import { _postMessage } from './message';
7
5
  import { Api, ApiConfigs, Lang, PointerMode } from './types';
8
6
  import type { LotteryProgramForPlayer } from './types.business';
7
+ import { CurrentInfo } from './types.business';
9
8
  import { delay, fetcher, imageLoaderSvg, setProps } from './util';
10
9
  import { _ } from './i18n';
11
10
 
@@ -23,19 +22,8 @@ export interface Option {
23
22
  name: string
24
23
  }
25
24
 
26
- const isUsingFakeData: boolean = false
27
-
28
25
  const fetcherApi = async <T extends Api>(api: T, endpoint: string, config: ApiConfigs[T]) => {
29
26
 
30
-
31
- if(isUsingFakeData){
32
- switch (api) {
33
- case Api.lotteries: return fakeResult
34
- case Api.draw: return fakeDraw
35
- }
36
- }
37
-
38
-
39
27
  const { session } = config
40
28
 
41
29
  const options = {
@@ -136,7 +124,9 @@ export const setMessage = (id: string, entry: string | object) => {
136
124
  }
137
125
  }
138
126
 
139
- export const getOptions = async (partitions: WheelOfFortunePartition[], lang: Lang) => {
127
+ export const getOptions = async (bonus: LotteryProgramForPlayer, lang: Lang) => {
128
+
129
+ const { partitions } = bonus.program.wheelOfFortune
140
130
 
141
131
  const preloadImage = async (src: string) => {
142
132
  if(!src) return {}
@@ -157,16 +147,27 @@ export const getOptions = async (partitions: WheelOfFortunePartition[], lang: La
157
147
  }
158
148
 
159
149
  export const getCurrentInfo = (
160
- lotteryProgramForPlayer: LotteryProgramForPlayer, key: 'active'|'implicit'
150
+ lotteryProgramForPlayer: LotteryProgramForPlayer,
151
+ key: CurrentInfo
161
152
  ) => {
162
153
 
163
154
  const { current } = lotteryProgramForPlayer
164
155
 
165
- return {
166
- active: current.activeTickets,
167
- implicit: `${current.maxImplicitTickets - current.usedImplicitTickets}/${current.maxImplicitTickets}`,
168
- remainingTimes: current.remainingTimes,
169
- }[key]
156
+ switch (key) {
157
+ case CurrentInfo.ActiveTickets:
158
+ return current.activeTickets
159
+
160
+ case CurrentInfo.ImplicitTickets:
161
+ const {
162
+ maxImplicitTickets: max,
163
+ usedImplicitTickets: used,
164
+ } = current
165
+
166
+ return `${max - used}/${max}`
167
+
168
+ case CurrentInfo.RemainingTimes:
169
+ return current.remainingTimes
170
+ }
170
171
  }
171
172
 
172
173
  export const api = {
@@ -246,8 +247,8 @@ export const checkIfNowIsBetween = (current) => {
246
247
 
247
248
  export const getSpinContainerSelector = (pointerMode: PointerMode) => {
248
249
  switch(pointerMode){
249
- case PointerMode.Arrow: return 'g.Partitions'
250
- case PointerMode.Partition: return 'g.Pointer'
250
+ case PointerMode.Arrow: return 'g.PartitionsContainer'
251
+ case PointerMode.Partition: return 'g.PointerContainer'
251
252
  }
252
253
  }
253
254
 
@@ -20,8 +20,6 @@ export abstract class Spinnable {
20
20
  if(!this.spinable) return;
21
21
 
22
22
  this.spinable = false
23
- console.log('x', this.arcStart);
24
- console.log('x', this.spinAngleStart);
25
23
  this.spinTimeTotal = 1000
26
24
  this.spinTime = 0;
27
25
  this.spinTick(fn)
@@ -44,11 +42,9 @@ export abstract class Spinnable {
44
42
  this.spinAngleStart,
45
43
  this.spinTimeTotal
46
44
  );
47
- console.log('ease', spinAngle);
48
45
 
49
46
 
50
47
  this.arcStart += convertDegToArc(spinAngle);
51
- console.log('arcStart', this.arcStart);
52
48
 
53
49
  this.tick()
54
50
  this.spinTimeout = setTimeout(this.spinTick.bind(this, fn), 10);
@@ -56,7 +52,6 @@ export abstract class Spinnable {
56
52
 
57
53
  private stop (fn){
58
54
  clearTimeout(this.spinTimeout);
59
- console.log(this.arcStart);
60
55
 
61
56
  this.afterStop()
62
57
  this.spinable = true
@@ -134,7 +134,6 @@ export class Spinner {
134
134
  const translation = target * easing(progress / duration) + startAngle;
135
135
  const speedCur = Math.abs(_easingGrad(progress / duration))
136
136
  //const speedRealCur = target / duration * Math.abs(_easingGrad(progress / duration)) * 33
137
- //console.log(this.param.loopSpeed, speedRealCur);
138
137
 
139
138
  this.setDeg(translation, speedCur)
140
139
 
@@ -6,136 +6,113 @@
6
6
  import './private.outcomes.svelte'
7
7
  import './private.item.svg.svelte'
8
8
 
9
- import { onMount } from 'svelte';
10
-
11
9
  // types
12
10
  import { Lang } from './types';
13
- import { getCurrentInfo, Option, setMessage } from './business';
11
+ import { getCurrentInfo } from './business';
14
12
  import { api } from './business';
15
13
  import { onMountMessageLifeCycle, _postMessage } from './message';
16
- import type { LotteryProgramForPlayer } from './types.business';
17
- import { classWithPart } from './util';
14
+ import { CurrentInfo, LotteryProgramForPlayer } from './types.business';
18
15
  import { _ } from './i18n';
16
+ import { setClientStyling } from './widget';
19
17
 
20
- // properties
18
+ // properties common
21
19
  export let lang: Lang = Lang.en
22
20
  export let endpoint: string = ''
23
21
  export let session: string = ''
22
+ export let clientstyling:string = ''
23
+ export let currentinfo: string = CurrentInfo.RemainingTimes
24
+ export let giftimagesrc: string = ''
25
+
26
+ // properties
27
+ export let id: string = ''
24
28
 
25
- export let lotteryprogramforplayer: string = undefined
26
-
27
- export let spinduration: string = '3'
28
- export let spinrotation: string = '3'
29
+ let rootContainer: HTMLElement
30
+ $: clientstyling && rootContainer && setClientStyling(rootContainer, clientstyling);
29
31
 
30
- // binds
31
- let main: HTMLElement;
32
+ $: commonProps = {
33
+ endpoint,
34
+ lang,
35
+ session,
36
+ clientstyling,
37
+ }
32
38
 
33
39
  // states
34
40
  let size: number = 0;
35
- let mainWidth: number = 0;
36
41
 
37
- let options: Option[] = [];
38
- let lotteryProgramForPlayer: LotteryProgramForPlayer
39
- let lotteryProgramForPlayerNew: LotteryProgramForPlayer
40
-
41
- $: lotteryProgramForPlayer = lotteryprogramforplayer && (JSON.parse(lotteryprogramforplayer)) as LotteryProgramForPlayer
42
- $: id = lotteryProgramForPlayer?.program?.id
42
+ let bonus: LotteryProgramForPlayer
43
+ let bonusNew: LotteryProgramForPlayer
43
44
 
44
45
  // lifecycles
45
46
  const init = async () => {
46
- await fetcher()
47
-
48
- mainWidth = main?.clientWidth
47
+ setTimeout(() => {
48
+ size = rootContainer?.clientWidth
49
+ }, 1)
49
50
  }
50
51
 
51
52
  const refetcher = async () => {
52
53
  const LotteryProgramsForPlayer = await api.lotteries(endpoint, session)
53
54
  return LotteryProgramsForPlayer.filter(l => l.program.id === id)[0]
54
55
  }
55
-
56
- const fetcher = async () => {
57
- try {
58
- if(!lotteryProgramForPlayer) return;
59
- render()
60
- } catch (e) {
61
- setMessage(id, e.message)
62
- }
63
- }
64
-
65
- const render = () => {
66
- if(!main) return;
67
- }
68
-
69
- onMount(() => {
70
- window.addEventListener('resize', render)
71
- return () => window.removeEventListener('resize', render)
72
- })
73
56
 
74
57
  onMountMessageLifeCycle({
58
+ 'wof-private-bonuses': (data) => {
59
+ bonus = data.bonuses.find(l => l.program.id === id)
60
+ },
75
61
  'wof-private-message-spin-after': (data) => {
76
62
  if(data.id !== id) return;
77
- lotteryProgramForPlayer = lotteryProgramForPlayerNew
63
+ bonus = bonusNew
78
64
  },
79
65
 
80
66
  'wof-private-message-spin-before': async (data) => {
81
67
  if(data.id !== id) return;
82
- lotteryProgramForPlayerNew = await refetcher()
68
+ bonusNew = await refetcher()
83
69
  },
84
70
  })
85
71
 
86
72
  // reactives
87
- $: lotteryProgramForPlayer && init()
88
- //
89
-
90
- $: size = mainWidth
91
-
92
- // ratio
73
+ $: bonus && init()
93
74
  $: ratio = size / 375
94
75
  $: radius = 247 / 2 * ratio
95
76
 
96
77
  </script>
97
78
 
98
- {#if lotteryProgramForPlayer}
99
-
100
- <div {...classWithPart("LotteryProgramWof")}>
101
-
102
- <div {...classWithPart("FortuneContainer")}>
103
- <main bind:this={main} {...classWithPart("Main")}>
104
-
105
- {#if size}
106
- <lottery-program-wof-private-item-svg {...{
107
- id,
108
- endpoint, session,
109
- sizeraw: size,
110
- lang,
111
- optionsraw: JSON.stringify(options),
112
- lotteryprogramforplayer: JSON.stringify(lotteryProgramForPlayer),
113
- }} />
114
- {/if}
115
-
116
- <lottery-program-wof-private-message-panel {...{
117
- id,
118
- r: radius,
119
- }} />
120
-
121
- </main>
122
-
123
- {#if lotteryProgramForPlayer.current}
124
- <div {...classWithPart("Current")}>
125
- <p>{$_('wof.ActiveTickets')}: {getCurrentInfo(lotteryProgramForPlayer, 'active')}</p>
126
- <p>{$_('wof.ImplicitTickets')}: {getCurrentInfo(lotteryProgramForPlayer, 'implicit')}</p>
127
- <p>{$_('wof.RemainingTimes')}: {getCurrentInfo(lotteryProgramForPlayer, 'remainingTimes')}</p>
128
- </div>
129
- {/if}
130
-
131
- </div>
79
+ <div class="LotteryItem" bind:this={rootContainer}>
80
+ <lottery-program-wof-private-item-svg {...{
81
+ ...commonProps,
82
+ id,
83
+ size,
84
+ }} />
85
+
86
+ <lottery-program-wof-private-message-panel {...{
87
+ ...commonProps,
88
+ id,
89
+ r: radius,
90
+ giftimagesrc,
91
+ }} />
92
+
93
+ {#if bonus?.current}
94
+ <div class="Current">
95
+ {#each currentinfo ? currentinfo.split(',') : [CurrentInfo.RemainingTimes] as CurrentInfoKey}
96
+ <p class={CurrentInfoKey}>
97
+ {$_(`wof.${CurrentInfoKey}`)}: {getCurrentInfo(bonus, CurrentInfoKey)}
98
+ </p>
99
+ {/each}
132
100
  </div>
133
- {/if}
101
+ {/if}
102
+
103
+ </div>
134
104
 
135
105
  <style lang="scss">
106
+ @mixin FortuneContainer {
107
+ width: 100%;
108
+ display: flex;
109
+ align-items: center;
110
+ flex-direction: column;
111
+ }
136
112
 
137
113
  lottery-program-wof-private-message-panel {
138
114
  position: absolute;
115
+ top: 0;
139
116
  }
140
117
 
141
118
 
@@ -154,118 +131,17 @@
154
131
  $outlineColor: rgb(150, 54, 88);
155
132
  $outlineWidth: 2px;
156
133
 
157
- .LotteryProgramWof {
158
- display: flex;
159
- align-items: center;
160
- flex-direction: column;
134
+ .LotteryItem {
135
+ @include FortuneContainer;
161
136
  padding: 20px 0;
162
- }
163
137
 
164
- main {
138
+ position: relative;
165
139
  max-width: 600px;
166
- width: 100%;
167
- display: flex;
168
140
  justify-content: space-around;
169
141
  min-height: 200px;
170
142
  }
171
143
 
172
- .Main {
173
- position: relative;
174
- }
175
-
176
- svg {
177
- transition: opacity 0.3s;
178
- }
179
-
180
- .HighLightArea {
181
- mix-blend-mode: color-dodge;
182
- }
183
-
184
- .HighLightAreaBackground {
185
- mix-blend-mode: screen;
186
- opacity: 0.41;
187
- }
188
-
189
- .HighLightAreaV1 {
190
- background: radial-gradient(72.02% 62.64% at 50% 84.62%, rgba(255, 184, 47, 0.7) 0%, rgba(255, 184, 47, 0.384271) 30.52%, rgba(255, 184, 47, 0.165346) 52.4%, rgba(255, 184, 47, 0) 100%);
191
- filter: blur(9px);
192
- }
193
- .HighLightAreaV2 {
194
- background: radial-gradient(87.18% 75.82% at 50% 84.62%, rgba(255, 248, 186, 0.7) 0%, rgba(255, 248, 186, 0.384271) 29.48%, rgba(255, 248, 186, 0) 100%);
195
- filter: blur(9px);
196
- }
197
-
198
- .FortuneContainer {
199
- width: 100%;
200
- display: flex;
201
- align-items: center;
202
- flex-direction: column;
203
- }
204
-
205
- .BackgroundCircle {
206
- fill: #FFFFFF;
207
- animation: color-animation 1s infinite linear alternate;
208
- }
209
-
210
- .RingCirclesGroup {
211
- .RingCircle {
212
- fill: #FFFFFF;
213
- stroke: #FFFFFF;
214
- }
215
- }
216
-
217
- .Center {
218
-
219
- transition: filter;
220
- transition-duration: 1s;
221
-
222
- &.disabled {
223
- filter: grayscale(80%);
224
- }
225
-
226
- .CenterCircle {
227
- fill: #3CE4BB;
228
- stroke: $outlineColor;
229
- stroke-width: $outlineWidth;
230
- cursor: pointer;
231
-
232
- transition: fill;
233
- transition-duration: 1s;
234
-
235
- }
236
-
237
- .CenterText {
238
- cursor: pointer;
239
- fill: #FFFFFF;
240
- }
241
- }
242
-
243
- .PointerPartition {
244
- opacity: 0.3;
245
- fill: lightgoldenrodyellow;
246
- stroke: red;
247
- stroke-width: 6px;
248
- stroke-dasharray: 12;
249
- }
250
-
251
- .PointerArrow {
252
- fill: #064CA0;
253
- }
254
-
255
144
  .Current {
256
145
  color: #FFFFFF;
257
146
  }
258
-
259
- .PartitionText {
260
- fill: #FFFFFF;
261
- font-style: normal;
262
- font-weight: 700;
263
- text-anchor: end;
264
- text-shadow: 0px 2px #000;
265
- }
266
-
267
- .PartitionShadow {
268
- background-blend-mode: multiply;
269
- mix-blend-mode: multiply;
270
- }
271
147
  </style>