Last active
January 21, 2017 17:55
-
-
Save mpkocher/d0d462ffdfd331b5a14734d33d29d08e to your computer and use it in GitHub Desktop.
Typescript PacBioOptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by mkocher on 1/21/17. | |
*/ | |
interface IdAble { | |
ix: string; | |
} | |
interface Primitive<T> { | |
value: T; | |
optionTypeId: string; | |
} | |
interface BaseOptionType<T> extends Primitive<T>, IdAble{ | |
name: string; | |
description: string | |
} | |
abstract class BaseOption<T> implements BaseOptionType<T> { | |
readonly ix: string; | |
readonly name: string; | |
readonly description: string; | |
readonly value: T; | |
readonly optionTypeId: string; | |
constructor(ix: string, name: string, description: string, value: T) { | |
this.ix = ix; | |
this.name = name; | |
this.description = description; | |
this.value = value; | |
} | |
summary(): string { | |
return `PacBioOption id:${this.ix} type:${this.optionTypeId} value:${this.value} name:${this.name} desc:${this.description}` | |
} | |
} | |
class IntOption extends BaseOption<number> { readonly optionTypeId = "integer" } | |
class StringOption extends BaseOption<string> {readonly optionTypeId = "string"} | |
class FloatOption extends BaseOption<number> { readonly optionTypeId = "float"} | |
interface ChoiceAble<T> { | |
choices: T[]; | |
} | |
abstract class BaseChoiceOption<T> implements BaseOptionType<T>, ChoiceAble<T> { | |
// This has to be duplicated because it's abstract? | |
readonly ix: string; | |
readonly name: string; | |
readonly description: string; | |
readonly optionTypeId: string; | |
readonly value: T; | |
public choices: T[]; | |
constructor(ix: string, name: string, description: string, value: T, choices: T[]) { | |
this.ix = ix; | |
this.name = name; | |
this.description = description; | |
this.value = value; | |
this.choices = choices; | |
} | |
summary(): string { | |
return `PacBioOption id:${this.ix} type:${this.optionTypeId} value:${this.value} choices:${this.choices} name:${this.name} desc:${this.description}` | |
} | |
} | |
class IntChoiceOption extends BaseChoiceOption<number> { readonly optionTypeId = "choice_integer"} | |
class StringChoiceOption extends BaseChoiceOption<string> {readonly optionTypeId = "choice_string"} | |
// This is a bit wrong. This needs to deal with the JsNumber -> Float casting | |
class FloatChoiceOption extends BaseChoiceOption<string> {readonly optionTypeId = "float_string"} | |
// This should probably be done via type bounds, but TS doesn't seem to | |
// have it. This is a workaround | |
type OptionType = IntOption | StringOption | FloatOption | IntChoiceOption | StringChoiceOption | FloatChoiceOption | |
/** | |
* Example of Iterating over a list of polymorphic option types | |
* | |
* @param opt | |
* @returns {string} | |
*/ | |
function toCustomSummary(opt: OptionType): string { | |
let sx = `Option Summary id:${opt.ix} value:${opt.value} type:${opt.optionTypeId}`; | |
// Running into problems here, because there's not a concrete choice type | |
// use "Type Guards?" | |
if (opt instanceof IntChoiceOption) { | |
return `${sx} choices:${opt.choices}` | |
} else { | |
return sx; | |
} | |
} | |
/** | |
* Return a Summary of the Task Options | |
* @param opts | |
* @returns {string} | |
*/ | |
function optionsSummary(opts: OptionType[]): string { | |
return opts.map(toCustomSummary).join("\n"); | |
} | |
/** | |
* Load From raw JSON from the services. This essentially | |
* a factory-ish pattern | |
* @param o | |
*/ | |
function loadFrom(o: Object): OptionType { | |
let optionTypeId = o['optionTypeId']; | |
switch(optionTypeId) { | |
// Add more types here. Each Option constructor might need an explicit validation of | |
// of type | |
case "integer": return new IntOption(o['id'], o['name'], o['description'], o['value']); | |
case "string": return new StringOption(o['id'], o['name'], o['description'], o['value']); | |
case "choice_string": return new StringChoiceOption(o['id'], o['name'], o['description'], o['value'], o['choices']) | |
} | |
} | |
function sanity(): boolean { | |
// Example of Raw json from the services for a PacBioOption | |
let o = { | |
id: "x", | |
optionTypeId: "integer", | |
name: "My Name", | |
description: "Description", | |
value: 1298 | |
}; | |
let o2 = { | |
id: "y", | |
optionTypeId: "choice_string", | |
name: "My Name", | |
description: "Description", | |
value: "alpha", | |
choices: ["alpha", "beta", "gamma"] | |
}; | |
let x = "description"; | |
let intOpt = new IntOption("a", "Alpha", x, 1234); | |
let strOpt = new StringOption("b", "Beta", x, "beta-value"); | |
let floatOpt = new FloatOption("g", "Gamma", x, 12345.0); | |
// choice examples | |
let intChoiceOpt = new IntChoiceOption("d", "delta", x, 1, [1,2,3]); | |
let strChoiceOpt = new StringChoiceOption("e", "epsilon", x, "a", ["a", "b", "c"]); | |
// Load and Convert Example from json | |
let myOption = loadFrom(o); | |
let myChoiceOpt = loadFrom(o2); | |
let opts: OptionType[] = [intOpt, strOpt, floatOpt, intChoiceOpt, strChoiceOpt, myOption, myChoiceOpt]; | |
console.log("Default Task Option Summary"); | |
console.log(opts.map(opt => opt.summary()).join("\n")); | |
let customSummary = optionsSummary(opts); | |
console.log("Custom Task Option Summary"); | |
console.log(customSummary); | |
return true; | |
} | |
sanity(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment