DEV Community

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on

5 4

Open Source Adventures: Episode 54: BATTLETECH Weapon Ranking App

Let's start coding the app. For now I'll hardcode some static assumptions like:

  • we don't care about crit damage
  • we don't care about stability damage
  • 10 ammo per weapon
  • 100% of heat compensated by single heat sinks, so 1 extra ton per 3 heat

Lodash sortBy

JavaScript standard library has an embarassing lack of a lot of basic functionality. I have little patience for writing it all myself every time, so we'll be using lodash for its sortBy function. Its API is quite inconvenient, but it works.

App.svelte

<script>
  import data from "./data.json"
  import Row from "./Row.svelte"
  import {sortBy} from "lodash"

  let round100 = (v) => Math.round(v * 100) / 100

  for (let row of data) {
    row.value = row.shots * row.baseDamage
    row.ammoWeight = round100(10 * row.ammoTonnagePerShot)
    row.cost = round100(row.tonnage + row.ammoWeight + row.heat/3.0)
    row.ratio = round100(row.value / row.cost)
  }

  let sortedData = sortBy(data, [(x) => -x.ratio, (x) => x.name])
</script>

<h1>BATTLETECH Weapons Data</h1>

<table>
  <tr>
    <th>Name</th>
    <th>Damage</th>
    <th>Heat</th>
    <th>Weight</th>
    <th>Ammo Weight</th>
    <th>Range</th>
    <th>Value</th>
    <th>Cost</th>
    <th>Ratio</th>
  </tr>
  {#each sortedData as row}
    <Row data={row} />
  {/each}
</table>

<style>
:global(body) {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
table :global(tr):nth-child(even) {
  background-color: #f2f2f2;
}
table :global(tr):nth-child(odd) {
  background-color: #e0e0e0;
}
</style>
Enter fullscreen mode Exit fullscreen mode

Here's the main component. We statically precalculate various derived data here. These assumptions will turn into sliders.

Some other points:

  • there's fairly messy :global to make odd/even shading work with tables across component boundary; it's not the only way, but it will do
  • let sortedData = sortBy(data, [(x) => -x.ratio, (x) => x.name]) is some really awkward API

Row.svelte

This component is much easier. Damage and Range column need some custom formatting. Range column could sure be a lot better with some colored bars instead.

Rounding to 2 decimal places could arguably be handled here instead of in the App component.

<script>
  export let data

  let {name, heat, shots, baseDamage, tonnage, minRange, maxRange, value, cost, ratio, ammoWeight} = data
  let damage
  if (shots == 1) {
    damage = baseDamage
  } else {
    damage = `${shots}x${baseDamage}`
  }
  let range = `${minRange}-${maxRange}`
</script>

<tr>
  <td>{name}</td>
  <td>{damage}</td>
  <td>{heat}</td>
  <td>{tonnage}</td>
  <td>{ammoWeight}</td>
  <td>{range}</td>
  <td>{value}</td>
  <td>{cost}</td>
  <td>{ratio}</td>
</tr>
Enter fullscreen mode Exit fullscreen mode

Story so far

All the code is on GitHub.

I deployed this on GitHub Pages, you can see it here.

Coming next

In the next episode I'll add some sliders to control assumptions made.

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Image of Docusign

πŸ› οΈ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

πŸ‘‹ Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay