|
| 1 | +namespace switchcase { |
| 2 | + |
| 3 | + |
| 4 | + /** |
| 5 | + * TODO: [X] Logic for Successful Execution Post-Action |
| 6 | + */ |
| 7 | + export enum SuccessRuleBehaviors { |
| 8 | + Unknown, |
| 9 | + Default, |
| 10 | + ClearCases, |
| 11 | + ClearMatchedCaseOnly, |
| 12 | + ClearAllNonDefaultCases, |
| 13 | + ClearAllCasesButMatchedCaseAndDefaultCase, |
| 14 | + ClearAllCasesButMatchedCase, |
| 15 | + } |
| 16 | + |
| 17 | + export class Case { |
| 18 | + public Name?: string; |
| 19 | + public Match: any; |
| 20 | + public Handler: () => void; |
| 21 | + public IsDefault?: boolean; |
| 22 | + |
| 23 | + constructor() { |
| 24 | + this.Name = null; |
| 25 | + this.Match = {}; |
| 26 | + this.Handler = null; |
| 27 | + this.IsDefault = false; |
| 28 | + } |
| 29 | + |
| 30 | + static createFrom ( name?: string, match any, handler: () => void, isDefault?: boolean): Case { |
| 31 | + let case: Case = new(); |
| 32 | + case.Name = name; |
| 33 | + case.Match = match; |
| 34 | + case.Handler = handler; |
| 35 | + case.IsDefault = isDefault; |
| 36 | + } |
| 37 | + |
| 38 | + static create( data: { Name?: string, Match: any, Handler: () => void, IsDefault?: boolean } ) : Case { |
| 39 | + return Case.createFrom(data.Name, data.Match, data.Handler, data.IsDefault); |
| 40 | + } |
| 41 | + |
| 42 | + static empty() : Case { |
| 43 | + return Case.createFrom(name: null, match: {}, handler: null, isDefault: false); |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + export class SwitchContext { |
| 48 | + private Cases: { Match: any, Handler: () => void, IsDefault?: boolean }[] = []; |
| 49 | + private TrueCases: Case[] = []; |
| 50 | + private Name: string; |
| 51 | + private Value: any; |
| 52 | + public IsValueSet: boolean; |
| 53 | + public OnExecutionSuccess_Default: boolean; |
| 54 | + public OnExecutionSuccess_ClearCases: boolean; |
| 55 | + public OnExecutionSuccess_ClearMatchedCaseOnly: boolean; |
| 56 | + public OnExecutionSuccess_ClearAllNonDefaultCases: boolean; |
| 57 | + public OnExecutionSuccess_ClearAllCasesButMatchedCase: boolean; |
| 58 | + public OnExecutionSuccess_ClearAllCasesButMatchedCaseAndDefaultCase: boolean |
| 59 | + |
| 60 | + protected SuccessRules: SuccessRuleBehaviors; |
| 61 | + |
| 62 | + constructor(name: string, value: any) { |
| 63 | + this.Value = value; |
| 64 | + this.Name = name; |
| 65 | + |
| 66 | + //TODO: [X] Add Clear Cases On Execute flag property |
| 67 | + this.IsValueSet = false; |
| 68 | + //this.OnExecutionSuccess_ClearCases = false; |
| 69 | + //this.SuccessRules = SuccessRuleBehaviors.Default; |
| 70 | + this.setExecutionSuccessRules(SuccessRuleBehaviors.Default); |
| 71 | + } |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | + addCase(match: any, handler: () => void): void { |
| 76 | + this.Cases.push({ Match: match, Handler: handler }); |
| 77 | + } |
| 78 | + |
| 79 | + addDefault(handler: () => void): void { |
| 80 | + this.Cases.push({ Match: null, Handler: handler, IsDefault: true }); |
| 81 | + } |
| 82 | + |
| 83 | + execute(): void { |
| 84 | + this.executeFromValue(this.Value); |
| 85 | + } |
| 86 | + |
| 87 | + executeFromValue(value: any): void { |
| 88 | + let matched = false; |
| 89 | + for (let cb of this.Cases) { |
| 90 | + if (cb.Match === value || cb.Match == value) { |
| 91 | + cb.Handler(); |
| 92 | + matched = true; |
| 93 | + break; |
| 94 | + } |
| 95 | + } |
| 96 | + if (!matched) { |
| 97 | + let defaultCase = this.Cases.find(cb => cb.IsDefault); |
| 98 | + if (defaultCase) defaultCase.Handler(); |
| 99 | + } |
| 100 | + //for now, let's keep the cases present, and instead of clearing them (for hygene), |
| 101 | + // let's instead go with a route that only sets them up the first time, and every other |
| 102 | + // time, instead of adding a case, the user would simply detect it already exists |
| 103 | + // and use what's there |
| 104 | + //this.Cases = []; // clear after execution |
| 105 | + } |
| 106 | + |
| 107 | + protected runExecutionSuccessRules(value: any, wasSuccessful?: boolean) { |
| 108 | + |
| 109 | + if(!wasSuccessful) |
| 110 | + return; |
| 111 | + |
| 112 | + var matchedCase = this.Cases.find(c => c.Match === value || c.Match == value); |
| 113 | + |
| 114 | + switch(this.SuccessRules) { |
| 115 | + |
| 116 | + case SuccessRuleBehaviors.ClearCases: |
| 117 | + this.clearCases(); |
| 118 | + break; |
| 119 | + case SuccessRuleBehaviors.ClearMatchedCaseOnly: |
| 120 | + if(matchedCase) |
| 121 | + //this.Cases.t |
| 122 | + break; |
| 123 | + case SuccessRuleBehaviors.ClearAllNonDefaultCases: |
| 124 | + |
| 125 | + break; |
| 126 | + case SuccessRuleBehaviors.ClearAllCasesButMatchedCaseAndDefaultCase: |
| 127 | + |
| 128 | + break; |
| 129 | + case SuccessRuleBehaviors.ClearAllCasesButMatchedCase: |
| 130 | + |
| 131 | + break; |
| 132 | + case SuccessRuleBehaviors.Default: |
| 133 | + case SuccessRuleBehaviors.Unknown: |
| 134 | + default: |
| 135 | + |
| 136 | + break; |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + setValue(value: any): void { |
| 141 | + this.Value = value; |
| 142 | + if (this.Value) |
| 143 | + this.IsValueSet = this.Value; |
| 144 | + else |
| 145 | + this.IsValueSet = false; |
| 146 | + } |
| 147 | + |
| 148 | + /** |
| 149 | + * TODO: [X] Added Logic For ClearCasesOnExecuteSuccess, setExecuteSuccessRule(SuccessRuleBehaviors); |
| 150 | + * enum SuccessRuleBehaviors { |
| 151 | + * Unknown, |
| 152 | + * Default, |
| 153 | + * ClearCases, |
| 154 | + * ClearMatchedCaseOnly, |
| 155 | + * ClearAllNonDefaultCases, |
| 156 | + * ClearAllCasesButMatchedCaseAndDefaultCase, |
| 157 | + * ClearAllCasesButMatchedCase, |
| 158 | + * } |
| 159 | + * Scenarios that might use each case above: |
| 160 | + * - ClearCases: The switch is a one-time deal for a one-off situation, so it needs to clear on execution. |
| 161 | + * - ClearMatchedCaseOnly: Picking up a pwr-up that matches the existing one causes it to disappear and be replaced with a more powerful variant (like missiles/rockets in Diddy Kong Racing). |
| 162 | + * - ClearAllNonDefaultCases: Picking up a special pwr-up replaces all non-default (non-HP/non-Shield/etc) pwr-ups with a brand new type that cannot exist while others are active. |
| 163 | + * - ClearAllCasesButMatchedCaseAndDefaultCase: Picking up the leaf in Super Mario Bros. 3 replaces tiny mario, fireball mario, jumping-boot mario, frog mario, etc with just Flying Racoon/Tanookie Mario + default/large mario (and visa versa with any pwr-up). |
| 164 | + * - ClearAllCasesButMatchedCase: Picking up tiny mario (realy tiny) in New Super Mario Bros 2 (3DS) will replace ALL mario variants with tiny mario (but does NOT reverse tiny mario if picked up again), and getting hit will not return you to tall mario or even small mario - it'll outright K.O. you... |
| 165 | + * |
| 166 | + */ |
| 167 | + setExecutionSuccessRules(successRules: SuccessRuleBehaviors ) { |
| 168 | + this.disableExecutionSuccessRules(); |
| 169 | + this.SuccessRules = successRules; |
| 170 | + |
| 171 | + switch(successRules) { |
| 172 | + case SuccessRuleBehaviors.ClearCases: |
| 173 | + this.OnExecutionSuccess_ClearCases = true; |
| 174 | + break; |
| 175 | + case SuccessRuleBehaviors.ClearMatchedCaseOnly: |
| 176 | + this.OnExecutionSuccess_ClearMatchedCaseOnly = true; |
| 177 | + break; |
| 178 | + case SuccessRuleBehaviors.ClearAllNonDefaultCases: |
| 179 | + this.OnExecutionSuccess_ClearAllNonDefaultCases = true; |
| 180 | + break; |
| 181 | + case SuccessRuleBehaviors.ClearAllCasesButMatchedCaseAndDefaultCase: |
| 182 | + this.OnExecutionSuccess_ClearAllCasesButMatchedCaseAndDefaultCase = true; |
| 183 | + break; |
| 184 | + case SuccessRuleBehaviors.ClearAllCasesButMatchedCase: |
| 185 | + this.OnExecutionSuccess_ClearAllCasesButMatchedCase = true; |
| 186 | + break; |
| 187 | + case SuccessRuleBehaviors.Default: |
| 188 | + case SuccessRuleBehaviors.Unknown: |
| 189 | + default: |
| 190 | + this.OnExecutionSuccess_Default = true; |
| 191 | + break; |
| 192 | + } |
| 193 | + } |
| 194 | + |
| 195 | + disableExecutionSuccessRules() { |
| 196 | + this.OnExecutionSuccess_ClearCases = false; |
| 197 | + this.OnExecutionSuccess_ClearMatchedCaseOnly = false; |
| 198 | + this.OnExecutionSuccess_ClearAllNonDefaultCases = false; |
| 199 | + this.OnExecutionSuccess_ClearAllCasesButMatchedCaseAndDefaultCase = false; |
| 200 | + this.OnExecutionSuccess_ClearAllCasesButMatchedCase = false; |
| 201 | + this.OnExecutionSuccess_Default = false; |
| 202 | + } |
| 203 | + |
| 204 | + resetExecutionSuccessRules() { |
| 205 | + this.setExecutionSuccessRules(SuccessRuleBehaviors.Default); |
| 206 | + } |
| 207 | + |
| 208 | + matches(match: any): boolean { |
| 209 | + return (this.Value == match || this.Value == match); |
| 210 | + } |
| 211 | + |
| 212 | + clearCases(): void { |
| 213 | + this.Cases = []; |
| 214 | + } |
| 215 | + |
| 216 | + /** |
| 217 | + * Remove Case (Non-Default Case) |
| 218 | + * and return both the success of removal and the removed case. |
| 219 | + * |
| 220 | + * Parameters: |
| 221 | + * @param {any} match |
| 222 | + * This is the match property found on your case. For DefaultCase, please see: {@look SwitchContext#removeDefaultCase} |
| 223 | + * @returns: |
| 224 | + * { removalSuccess: boolean, removed: { Match: any, Handler: () => void, IsDefault?: boolean } } |
| 225 | + */ |
| 226 | + removeCase(match: any): { RemovalSuccess: boolean, Removed: { Match: any, Handler: () => void, IsDefault?: boolean } | undefined } { |
| 227 | + |
| 228 | + /* |
| 229 | + let toRemove: { Match: any, Handler: () => void, IsDefault?: boolean }; |
| 230 | + let matched = false; |
| 231 | + |
| 232 | + for (let cb in this.Cases) { |
| 233 | + if (cb.Match === match || cb.Match == match) { |
| 234 | + toRemove = cb; |
| 235 | + matched = true; |
| 236 | + break; |
| 237 | + } |
| 238 | + } |
| 239 | + */ |
| 240 | + |
| 241 | + let toRemove: { Match: any, Handler: () => void, IsDefault?: boolean } | undefined; |
| 242 | + let removeSuccess = false; |
| 243 | + |
| 244 | + let tmp = |
| 245 | + this.Cases.find(cb => cb.Match === match || cb.Match == match); |
| 246 | + |
| 247 | + if(tmp) |
| 248 | + toRemove = tmp; |
| 249 | + |
| 250 | + if (toRemove) removeSuccess = this.Cases.remove(toRemove); |
| 251 | + //if (removeSuccess) return toRemove; |
| 252 | + |
| 253 | + return { RemovalSuccess: removeSuccess, Removed: toRemove }; |
| 254 | + |
| 255 | + /* |
| 256 | + if(match.IsDefault) |
| 257 | + |
| 258 | + if (match.IsDefault) { |
| 259 | + toRemove = this.Cases.find(cb => cb.IsDefault); |
| 260 | + if (toRemove) { |
| 261 | + if (this.Cases.removeElement(defaultCase)) return defaultCase; |
| 262 | + } |
| 263 | + } |
| 264 | + */ |
| 265 | + |
| 266 | + } |
| 267 | + |
| 268 | + /** |
| 269 | + * Remove Default Case |
| 270 | + * and return both the success of removal and the removed case |
| 271 | + * To remove a specific NON-Default case, please see: {@see SwitchContext#removeCase} |
| 272 | + * |
| 273 | + * Parameters: |
| 274 | + * NONE |
| 275 | + * Returns: |
| 276 | + * @returns: |
| 277 | + * { RemovalSuccess: boolean, Removed: { Match: any, Handler: () => void, IsDefault?: boolean } } |
| 278 | + * The success of finding and removing the defaultCaseBlock AND the defaultCaseBlock that was removed. |
| 279 | + */ |
| 280 | + removeDefaultCase(): { |
| 281 | + RemovalSuccess: boolean |
| 282 | + , Removed: { Match: any, Handler: () => void, IsDefault?: boolean } |
| 283 | + } { |
| 284 | + |
| 285 | + let defaultCaseBlock: { Match: any, Handler: () => void, IsDefault?: boolean } | undefined; |
| 286 | + let found = this.Cases.find(dcb => dcb.IsDefault); |
| 287 | + if(found) |
| 288 | + defaultCaseBlock = found; |
| 289 | + |
| 290 | + let returnValue: { |
| 291 | + RemovalSuccess: boolean, |
| 292 | + Removed: { |
| 293 | + Match: any |
| 294 | + , Handler: () => void |
| 295 | + , IsDefault?: boolean |
| 296 | + } } = { |
| 297 | + RemovalSuccess: false, |
| 298 | + Removed: { |
| 299 | + Match: {}, |
| 300 | + Handler: () => return, |
| 301 | + IsDefault: true, |
| 302 | + } }; |
| 303 | + |
| 304 | + if (defaultCaseBlock) { |
| 305 | + this.Cases.remove(defaultCaseBlock); |
| 306 | + returnValue.RemovalSuccess = true; |
| 307 | + returnValue.Removed == defaultCaseBlock; |
| 308 | + } |
| 309 | + else { |
| 310 | + returnValue.RemovalSuccess = false; |
| 311 | + returnValue.Removed = defaultCaseBlock; |
| 312 | + } |
| 313 | + |
| 314 | + return returnValue; |
| 315 | + } |
| 316 | + |
| 317 | + caseCount(): number { |
| 318 | + return this.Cases.length; |
| 319 | + } |
| 320 | + /** |
| 321 | + * class SwitchContext { |
| 322 | + * [private] Cases { Match: any, handler: () => void, IsDefault?: boolean }[] |
| 323 | + * addCase(match: any, handler: () => void): void; |
| 324 | + * addDefault(handler: () => void): void; |
| 325 | + * execute(value: any): void; |
| 326 | + * caseCount(): number; |
| 327 | + * } |
| 328 | + */ |
| 329 | + } |
| 330 | +} |
0 commit comments