fortel-ziweidoushu
Version:
紫微斗數排盤 Zi Wei Dou Shu
392 lines (325 loc) • 10.7 kB
text/typescript
import { Ground } from './ground'
import { LifeStage } from './lifeStage'
import { MajorStar } from './majorStar'
import { MiniStar } from './miniStar'
import { MinorStar } from './minorStar'
import { Sky } from './sky'
import { Temple } from './temple'
import util from 'util'
import { mod } from './../utils'
import { Star } from './star'
class Cell {
#sky: Sky
#ground: Ground
#temples: Temple[] = []
#majorStars: MajorStar[] = []
#minorStars: MinorStar[] = []
#miniStars: MiniStar[] = []
#borrowCells: Readonly<BorrowCell>[] = []
#leaderStar?: MiniStar
#yearGodStar?: MiniStar
#scholarStar?: MiniStar
#ageStart?: number
#lifeStage?: LifeStage
//metadata
#cellIndex?: number
//cells: Cell[] = []
#prevCell?: Cell
#nextCell?: Cell
constructor(sky: Sky, ground: Ground) {
this.#sky = sky
this.#ground = ground
}
get sky(): Sky {
return this.#sky
}
get ground(): Ground {
return this.#ground
}
get temples(): Temple[] {
return this.#temples
}
get majorStars(): MajorStar[] {
return this.#majorStars
}
get minorStars(): MinorStar[] {
return this.#minorStars
}
get miniStars(): MiniStar[] {
return this.#miniStars
}
get allStars(): Star[] {
return [...this.#majorStars, ...this.#minorStars, ...this.allMiniStars]
}
get allMiniStars(): MiniStar[] {
return [...this.#miniStars, this.#scholarStar!, this.#yearGodStar!, this.#leaderStar!]
}
get borrowCells(): Readonly<BorrowCell>[] {
return this.#borrowCells
}
get leaderStar(): MiniStar {
if (this.#leaderStar) {
return this.#leaderStar
}
throw new Error('Leader Star not found.')
}
set leaderStar(leaderStar: MiniStar) {
this.#leaderStar = leaderStar
}
get yearGodStar(): MiniStar {
if (this.#yearGodStar) {
return this.#yearGodStar
}
throw new Error('Year God Star not found.')
}
set yearGodStar(yearGodStar: MiniStar) {
this.#yearGodStar = yearGodStar
}
get scholarStar(): MiniStar {
if (this.#scholarStar) {
return this.#scholarStar
}
throw new Error('Scholar Star not found.')
}
set scholarStar(scholarStar: MiniStar) {
this.#scholarStar = scholarStar
}
get ageStart(): number {
if (this.#ageStart !== undefined) {
return this.#ageStart
}
throw new Error('Age Start not found.')
}
set ageStart(ageStart: number) {
this.#ageStart = ageStart
}
get ageEnd(): number {
if (this.#ageStart !== undefined) {
return this.#ageStart + 9
}
throw new Error('Age End not found.')
}
get lifeStage(): LifeStage {
if (this.#lifeStage !== undefined) {
return this.#lifeStage
}
throw new Error('Life Stage not found.')
}
set lifeStage(lifeStage: LifeStage) {
this.#lifeStage = lifeStage
}
get cellIndex(): number {
if (this.#cellIndex !== undefined) {
return this.#cellIndex
}
throw new Error('Cell Index not found.')
}
set cellIndex(cellIndex: number) {
this.#cellIndex = cellIndex
}
get prevCell(): Cell {
if (this.#prevCell !== undefined) {
return this.#prevCell
}
throw new Error('prevCell not found.')
}
set prevCell(cell: Cell) {
this.#prevCell = cell
}
get nextCell(): Cell {
if (this.#nextCell !== undefined) {
return this.#nextCell
}
throw new Error('nextCell not found.')
}
set nextCell(cell: Cell) {
this.#nextCell = cell
}
get self(): Cell {
return this
}
getPrevICell(i: number): Cell {
if (i < 0) {
return this.getNextICell(-i)
}
let cell: Cell = this.self
for (let j = 0; j < i; j++) {
if (cell.prevCell === undefined) {
throw new Error('Prev Cell not defined!')
}
cell = cell.prevCell
}
return cell
// return this.cells![mod(this.cellIndex! - i, this.cells!.length)]
}
getNextICell(i: number): Cell {
if (i < 0) {
return this.getPrevICell(-i)
}
let cell: Cell = this.self
for (let j = 0; j < i; j++) {
if (cell.nextCell === undefined) {
throw new Error('Next Cell not defined!')
}
cell = cell.nextCell
}
return cell
// return this.cells![mod(this.cellIndex! + i, this.cells!.length)]
}
getCellNextDist(cell: Cell): number {
return mod(cell.cellIndex - this.cellIndex, 12)
}
getCellPrevDist(cell: Cell): number {
return mod(this.cellIndex - cell.cellIndex, 12)
}
getCellDist(cell: Cell): number {
const nextDist = this.getCellNextDist(cell)
return Math.min(nextDist, 12 - nextDist)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
[util.inspect.custom](depth: number, opts: any): string {
return util.inspect(this.toJSON(), opts)
}
toJSON() {
return {
sky: this.#sky,
ground: this.#ground,
temples: this.#temples,
majorStars: this.#majorStars,
minorStars: this.#minorStars,
miniStars: this.#miniStars,
miscStars: this.allMiniStars,
ageStart: this.#ageStart,
ageEnd: this.#ageStart ? this.ageEnd : undefined,
lifeStage: this.#lifeStage,
}
}
toString(): string {
return (
`Cell {${this.sky.displayName}${this.ground.displayName}, temples=[${this.temples}]` +
`, majorStars=[${this.majorStars?.map(
(star) => star.displayName + ' ' + MajorStar.majorStarPlacers.get(star)?.evalEnergyLevel(this.ground!),
)}]` +
`, minorStars=[${this.minorStars}]` +
`, miniStars=[${this.miniStars}], miscStars=[${[this.#scholarStar, this.#yearGodStar, this.#leaderStar]}]` +
`, ageRange=[${this.#ageStart ?? ''}-${this.#ageStart ? this.#ageStart + 9 : ''}], lifeStage=[${this.#lifeStage ?? ''}]` +
`}`
)
}
equals(cell: Cell) {
if (this === cell) {
return true
} else if (this.toJSON() === cell.toJSON()) {
return true
}
return false
}
get selfWithBorrow(): Cell[] {
return [this, ...this.#borrowCells.map((borrowCell) => borrowCell.cell)]
}
get oppositeCell(): Cell {
return this.getNextICell(6)
}
get oppositeCellWithBorrow(): Cell[] {
return this.oppositeCell.selfWithBorrow
}
get selfOppositeCells(): [Cell, Cell] {
return [this, this.oppositeCell]
}
get selfOppositeCellsWithBorrow(): Cell[] {
return Cell.cellsWithBorrowCells([this, this.oppositeCell])
}
get supportCells(): [Cell, Cell] {
return [this.getNextICell(4), this.getPrevICell(4)]
}
get supportCellsWithBorrow(): Cell[] {
return Cell.cellsWithBorrowCells(this.supportCells)
}
get triangleCells(): [Cell, Cell, Cell] {
return [this, ...this.supportCells]
}
get triangleCellsWithBorrow(): Cell[] {
return Cell.cellsWithBorrowCells(this.triangleCells)
}
get fourCells(): [Cell, Cell, Cell, Cell] {
return [this, this.oppositeCell, ...this.supportCells]
}
get fourCellsWithBorrow(): Cell[] {
return Cell.cellsWithBorrowCells(this.fourCells)
}
static cellsWithBorrowCells(cells: Cell[]): Cell[] {
const allCells: Cell[] = cells.flatMap((cell) => {
return [cell, ...cell.#borrowCells.map((borrowCell) => borrowCell.cell)]
})
const uniqueCells = allCells.filter((value, index, array) => {
return array.indexOf(value) === index
})
return uniqueCells
}
hasMajorMinorStar(targetStar: Star): boolean {
return !!(
this.#majorStars.find((star: MajorStar) => {
return star.equals(targetStar)
}) ??
this.#minorStars.find((star: MinorStar) => {
return star.equals(targetStar)
})
)
}
hasStarInstance(targetStar: Star): boolean {
return !!(
this.#majorStars.find((star: MajorStar) => {
return star.equals(targetStar)
}) ??
this.#minorStars.find((star: MinorStar) => {
return star.equals(targetStar)
}) ??
this.allMiniStars.find((star: MinorStar) => {
return star.equals(targetStar)
})
)
}
hasStar(targetStar: Star): boolean {
return !!(
this.#majorStars.find((star: MajorStar) => {
return star.equals(targetStar)
}) ??
this.#minorStars.find((star: MinorStar) => {
return star.equals(targetStar)
}) ??
this.allMiniStars.find((star: MinorStar) => {
return star.getDisplayName() === targetStar.getDisplayName()
})
)
}
hasAllStars(targetStars: Star[]): boolean {
for (const targetStar of targetStars) {
if (!this.hasStar(targetStar)) {
return false
}
}
return true
}
hasAnyStars(targetStars: Star[]): boolean {
for (const targetStar of targetStars) {
if (this.hasStar(targetStar)) {
return true
}
}
return false
}
hasTemple(targetTemple: Temple): boolean {
return !!this.temples.find((temple: Temple) => {
return temple.equals(targetTemple)
})
}
}
class BorrowCell {
cell: Cell
cellRatio: number
constructor(cell: Cell, cellRatio: number) {
this.cell = cell
this.cellRatio = cellRatio
}
}
export { Cell, BorrowCell }