Passed
Push — main ( 7220bc...7973a7 )
by Dylan
04:29
created

Polyrat.toHTMLFormula   B

Complexity

Conditions 8

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 17
dl 0
loc 25
ccs 14
cts 14
cp 1
crap 8
rs 7.3333
c 0
b 0
f 0
1 2
import {Rat} from './Rat'
2 2
import Symbolizer from './Symbolizer'
3
4
export interface Coefficents<Rat> {
5
  [Key: string]: Rat;
6
}
7
8
/**
9
 * @class Rational polynumber
10
 * @name Polyrat
11
 */
12 2
export class Polyrat {
13
14
  // coefficent values are indexed with their the exponents in each dimension, comma-separated, as the key
15 14
  coefficents: Coefficents<Rat> = {}
16
17
  // the dimension is how many params there are, defined by the length of the exponent keys
18 14
  dimension = 0
19
20
  // unique symbols for each dimension
21 14
  symbols = ''
22
23
  /**
24
   * Initialize a rational polynumber.
25
   */
26
  constructor(coefficents?: Coefficents<Rat>) {
27 14
    if (coefficents) {
28
      // for (const i in coefficents) {
29
      //   if (typeof coefficents[i] !== typeof Rat) {
30
      //     // coefficents[i] = new Rat(coefficents[i])
31
      //   }
32
      // }
33 12
      this.coefficents = coefficents
34
    }
35 14
    if (Object.keys(this.coefficents).length) {
36 8
      this.dimension = Object.keys(this.coefficents)[0].split(',').length
37
    }
38 14
    const sg = (new Symbolizer('xyzw')).generator()
39 14
    for (let i=0; i<this.dimension; i++) {
40 12
      this.symbols += sg.next().value
41
    }
42
  }
43
44
  /**
45
   * Evaluate the result given the parameters for each dimension.
46
   */
47
  evaluate(parameters: Rat[]): Rat {
48 1
    let result: Rat = new Rat()
49 1
    for (const [exponents, coefficent] of Object.entries(this.coefficents)) {
50 1
      let value: Rat = coefficent
51 1
      const dimensions = exponents.split(',')
52 1
      for (let i=0; i<dimensions.length; i++) {
53 1
        value = value.mul(parameters[i].pow(new Rat(parseInt(dimensions[i], 10))))
54
      }
55 1
      result = result.add(value)
56
    }
57 1
    return result
58
  }
59
60
  /**
61
   * The text representation.
62
   */
63
  toString(): string {
64 2
    return `${this.constructor.name}(${this.toJSON()})`
65
  }
66
67
  /**
68
   * The JSON representation.
69
   */
70
  toJSON(): string {
71
    // return JSON.stringify(this.coefficents)
72 3
    const r = []
73 3
    for (const [exponents, coefficent] of Object.entries(this.coefficents)) {
74 7
      r.push(`'${exponents}':'${coefficent.toString()}'`)
75
    }
76 3
    return `[${r.join(',')}]`
77
  }
78
79
  /**
80
   * The formula in the human way with exponents as HTML sups.
81
   */
82
  toHTMLFormula(): string {
83 5
    const r: string[] = []
84 5
    for (const [exponents, coefficent] of Object.entries(this.coefficents)) {
85 12
      const t: string[] = []
86 12
      const f = coefficent.toString()
87 12
      if (f !== '1') t.push(f)
88 12
      const dimensions = exponents.split(',')
89 12
      for (let i=0; i<dimensions.length; i++) {
90 24
        if (dimensions[i] !== '0') {
91 12
          if (dimensions[i] === '1') {
92 3
            t.push(this.symbols[i])
93
          }
94
          else {
95 9
            t.push(`${this.symbols[i]}<sup>${parseInt(dimensions[i], 10)}</sup>`)
96
          }
97
        }
98
      }
99 12
      if (t) r.push(t.join(''))
100
    }
101 5
    if (r.length === 0) return '0'
102 4
    return r.join(' + ')
103
  }
104
105
  /**
106
   * The "calc" code for evaluating the value.
107
   */
108
  toCalcFormula(): string {
109 5
    const r: string[] = []
110 5
    for (const [exponents, coefficent] of Object.entries(this.coefficents)) {
111 11
      const t: string[] = []
112 11
      const f = coefficent.toString()
113 11
      if (f !== '1') t.push(f)
114 11
      const dimensions = exponents.split(',')
115 11
      for (let i=0; i<dimensions.length; i++) {
116 20
        if (dimensions[i] !== '0') {
117 11
          if (dimensions[i] === '1') {
118 4
            t.push(this.symbols[i])
119
          }
120
          else {
121 7
            t.push(`${this.symbols[i]}^${parseInt(dimensions[i], 10)}`)
122
          }
123
        }
124
      }
125 11
      if (t) r.push(t.join('*'))
126
    }
127 5
    if (r.length === 0) return '0'
128 4
    return r.join(' + ')
129
  }
130
131
  /**
132
   * The GLSL code for evaluating the value.
133
   */
134
  toGLSLFormula(): string {
135 2
    const r: string[] = []
136 2
    for (const [exponents, coefficent] of Object.entries(this.coefficents)) {
137 5
      const t: string[] = []
138 5
      const f = coefficent.toString()
139 5
      if (f !== '1') t.push(f+'.0')
140 5
      const dimensions = exponents.split(',')
141 5
      for (let i=0; i<dimensions.length; i++) {
142 10
        if (dimensions[i] !== '0') {
143 6
          t.push(`pow(${this.symbols[i]},${parseInt(dimensions[i], 10)}.0)`)
144
        }
145
      }
146 5
      if (t) r.push(t.join('*'))
147
    }
148 2
    if (r.length === 0) return '0'
149 1
    return r.join('+')
150
  }
151
152
  /**
153
   * Clone this.
154
   */
155
  clone(): Polyrat {
156 1
    return new Polyrat(this.coefficents)
157
  }
158
159
}
160
161
/**
162
 * Parse the string and return it as a Polyrat.
163
 */
164 2
export const stringToPolyrat = (s: string): Polyrat => {
165 1
  return new Polyrat(JSON.parse(s) as Coefficents<Rat>)
166
}
167
168
export default Polyrat
169