MrZeeba / boss-master

An Android/IOs app designed to aid and assist scoring in Archery
1 stars 0 forks source link

Swap data objects to types #66

Closed MrZeeba closed 1 month ago

MrZeeba commented 1 month ago

Having them as types instead of json files offers me type checking. When using my custom components this means I can ensure they follow the correct data structure and can remove nasty type casts like this

export function OutdoorSessionComponent() {
  const outdoorData: ObjectWithDisplayName = RoundData.types.outdoor
    .rounds as unknown as ObjectWithDisplayName;

This can be achieved like this

// Types.ts
export interface Variation {
  displayName: string;
  distances: number[];
}

export interface Distance {
  distance: number;
  arrows: number;
}

export interface Round {
  displayName: string;
  distanceType: string;
  faceSize: number;
  zoneScoring: number;
  arrowsPerEnd: number;
  arrowsAtEachDistance?: number;
  variations?: Variation[];
  distances?: Distance[];
}

export interface RoundType {
  [key: string]: Round;
}

export interface RoundTypes {
  [key: string]: {
    displayName: string;
    rounds: RoundType;
  };
}

export interface RootObject {
  types: RoundTypes;
}
// Data.ts
import { RootObject } from './Types';

const data: RootObject = {
  "types": {
    "practice": {
      "displayName": "Practice"
    },
    "outdoor": {
      "displayName": "Outdoor",
      "rounds": {
        "shortmetric": {
          "displayName": "Short Metric",
          "distanceType": "metric",
          "faceSize": 80,
          "zoneScoring": 10,
          "arrowsPerEnd": 6,
          "arrowsAtEachDistance": 36,
          "variations": [
            { "displayName": "I", "distances": [70, 60] },
            { "displayName": "II", "distances": [60, 50] },
            { "displayName": "III", "distances": [50, 40] },
            { "displayName": "IV", "distances": [40, 30] },
            { "displayName": "V", "distances": [30, 20] }
          ]
        },
        "longmetric": {
          "displayName": "Long Metric",
          "distanceType": "metric",
          "faceSize": 122,
          "zoneScoring": 10,
          "arrowsPerEnd": 6,
          "arrowsAtEachDistance": 36,
          "variations": [
            { "displayName": "I", "distances": [90, 70] },
            { "displayName": "II", "distances": [70, 60] },
            { "displayName": "III", "distances": [50, 40] },
            { "displayName": "IV", "distances": [40, 30] },
            { "displayName": "V", "distances": [30, 20] }
          ]
        },
        "york": {
          "displayName": "York",
          "distanceType": "imperial",
          "faceSize": 122,
          "zoneScoring": 5,
          "arrowsPerEnd": 6,
          "distances": [
            {
              "distance": 100,
              "arrows": 72
            },
            {
              "distance": 80,
              "arrows": 48
            },
            {
              "distance": 60,
              "arrows": 24
            }
          ]
        }
      }
    },
    "indoor": {
      "displayName": "Indoor",
      "rounds": {
        "portsmouth": {
          "displayName": "Portsmouth",
          "distanceType": "imperial",
          "faceSize": 60,
          "zoneScoring": 10,
          "arrowsPerEnd": 6,
          "arrowsAtEachDistance": 60
        }
      }
    }
  }
};

export default data;