d4-refactor-orders--moonshotai-kimi-k3

The attached module computes order totals and works, but it is exactly the kind of code AI assistants produce: redundant machinery, type laundering, narration comments, a needless wrapper layer. Rewrite it as a clean TypeScript module of the same public behavior (computeTotal, applyDiscount, summarize are called by other code and their signatures must keep accepting the same inputs). Do not change observable behavior. Add focused tests for the discount and rounding edges. Accompany the code with a brief explanation of what you changed and why.

ModelKimi K3 (Moonshot) moonshotai/kimi-k3
Taskd4-refactor-orders · refactor · typescript · tests expected
Harnessopenrouter-chat-completions openrouter-chat-2026-09-22 at temperature 0.3
Generated2026-09-22T14:35:08.257Z (generated)
LicenseMIT · demo-eligible
ContaminationNot previously public · No viral exposure recorded

Prompt

The attached module computes order totals and works, but it is exactly the kind of code AI assistants produce: redundant machinery, type laundering, narration comments, a needless wrapper layer. Rewrite it as a clean TypeScript module of the same public behavior (computeTotal, applyDiscount, summarize are called by other code and their signatures must keep accepting the same inputs). Do not change observable behavior. Add focused tests for the discount and rounding edges. Accompany the code with a brief explanation of what you changed and why. The module below is the starting point. Apply the required changes and re-emit the ENTIRE file as one block — never a diff, patch, or excerpt. Seed file `orderTotals.ts`: ```typescript // This module handles order total calculation stuff // It computes the totals for orders and applies discounts as needed import { Order, Item, Result } from './types'; // Step 1: validate the items in the order function validateItems(items: any): boolean { // check that items is valid if (items == null) { return false; } if (!Array.isArray(items)) { return false; } // loop through items and validate each one for (let index = 0; index < items.length; index++) { const currentItem = items[index]; if (typeof currentItem !== 'object') { return false; } if (currentItem.price == undefined) { return false; } if (typeof currentItem.price !== 'number') { return false; } if (currentItem.qty == undefined) { return false; } } return true; } // helper to round money values to 2 decimal places function roundMoney(value: number): number { // rounds to 2 decimals return Math.round(value * 100) / 100; } // computes line total for a single item function computeLineTotal(item: any): number { const price: number = (item as any).price; const qty: number = (item as any).qty as number; const lineTotal = price * qty; return roundMoney(lineTotal); } // wraps computeLineTotal with extra safety function safeLineTotal(item: Item): number { try { return computeLineTotal(item); } catch (e) { return 0; } } export function computeTotal(order: Order): number { // Step 2: compute the total let total = 0; const items = (order as any).items as any[]; if (!validateItems(items)) { return 0; } for (let index = 0; index < items.length; index++) { total = total + safeLineTotal(items[index]); } // Step 3: round and return return roundMoney(total); } export function applyDiscount(total: number, code: string | null | undefined): number { // applies a discount code to the total let result = total; if (code !== null && code !== undefined && code !== '') { if (code === 'SAVE10') { result = result * 0.9; } else if (code === 'SAVE20') { result = result * 0.8; } else if (code === 'HALFOFF') { result = result * 0.5; } else { // unknown code: no discount result = result * 1; } } return roundMoney(result); } // builds a summary object with the total, item count, and discount info export function summarize(order: Order, code?: string | null): Result { const total = computeTotal(order); const discounted = applyDiscount(total, code); const summary = { status: 'success', ok: true, total: total, discounted: discounted, itemCount: (order as any).items.length, savings: roundMoney(total - discounted), }; return summary as unknown as Result; } ``` ## Output contract First, write a brief explanation of your design choices — plain prose, no code fences. Then emit exactly one fenced code block per file, and no other text between or after the blocks: - The FIRST line of every block is that file's marker line: - TypeScript or JavaScript: `// FILE: <path>` - Python: `# FILE: <path>` - A single-file web app is one file named `index.html`, so its marker line is `// FILE: index.html`. - Everything after the marker line is that file complete, from its first line to its last — no diffs, no omissions, no placeholders. - Tag each fence with the file's language, for example ```html, ```typescript, ```python.

Artifact

Form: tree

orderTotals.ts

import type { Order, Item, Result } from './types';

const DISCOUNT_MULTIPLIERS = new Map<string, number>([
  ['SAVE10', 0.9],
  ['SAVE20', 0.8],
  ['HALFOFF', 0.5],
]);

function roundMoney(value: number): number {
  return Math.round(value * 100) / 100;
}

// Runtime shape check with the original acceptance rules, quirks included:
// qty's type is not checked (the multiplication coerces it), and a null
// element throws on property access instead of failing validation cleanly.
function isValidItem(item: unknown): item is Item {
  if (typeof item !== 'object') {
    return false;
  }
  const candidate = item as Item;
  return (
    candidate.price != null &&
    typeof candidate.price === 'number' &&
    candidate.qty != null
  );
}

// The try/catch is load-bearing: a qty that passes validation but cannot be
// multiplied (BigInt, Symbol) contributes 0 to the total rather than throwing.
function lineTotal(item: Item): number {
  try {
    return roundMoney(item.price * item.qty);
  } catch {
    return 0;
  }
}

export function computeTotal(order: Order): number {
  const items = order.items;
  if (!Array.isArray(items)) {
    return 0;
  }
  // Validate every item before summing: one bad item zeroes the whole order.
  for (const item of items) {
    if (!isValidItem(item)) {
      return 0;
    }
  }
  let total = 0;
  for (const item of items) {
    total += lineTotal(item);
  }
  return roundMoney(total);
}

export function applyDiscount(total: number, code: string | null | undefined): number {
  const multiplier = code ? (DISCOUNT_MULTIPLIERS.get(code) ?? 1) : 1;
  return roundMoney(total * multiplier);
}

export function summarize(order: Order, code?: string | null): Result {
  const total = computeTotal(order);
  const discounted = applyDiscount(total, code);
  return {
    status: 'success',
    ok: true,
    total,
    discounted,
    itemCount: order.items.length,
    savings: roundMoney(total - discounted),
  };
}

orderTotals.test.ts

import { describe, it, expect } from 'vitest';
import { computeTotal, applyDiscount, summarize } from './orderTotals';
import type { Order } from './types';

describe('applyDiscount', () => {
  it('applies the known codes', () => {
    expect(applyDiscount(100, 'SAVE10')).toBe(90);
    expect(applyDiscount(100, 'SAVE20')).toBe(80);
    expect(applyDiscount(100, 'HALFOFF')).toBe(50);
  });

  it('leaves the total unchanged for unknown, empty, null, or undefined codes', () => {
    expect(applyDiscount(100, 'NOPE')).toBe(100);
    expect(applyDiscount(100, '')).toBe(100);
    expect(applyDiscount(100, null)).toBe(100);
    expect(applyDiscount(100, undefined)).toBe(100);
  });

  it('is case-sensitive and does not trim whitespace', () => {
    expect(applyDiscount(100, 'save10')).toBe(100);
    expect(applyDiscount(100, 'SAVE10 ')).toBe(100);
  });

  it('rounds after discounting: 19.99 at 10% off is 17.99', () => {
    expect(applyDiscount(19.99, 'SAVE10')).toBe(17.99);
  });

  it('rounds up when the halved value lands just above the half cent', () => {
    // 7.95 is stored slightly above its decimal value, so halving it lands
    // just above 3.975 and Math.round pushes it to 3.98.
    expect(applyDiscount(7.95, 'HALFOFF')).toBe(3.98);
  });

  it('still rounds the total when no code is given', () => {
    expect(applyDiscount(1.005, null)).toBe(1);
  });
});

describe('computeTotal rounding', () => {
  it('rounds halves up: 0.125 becomes 0.13', () => {
    expect(computeTotal({ items: [{ price: 0.125, qty: 1 }] })).toBe(0.13);
  });

  it('rounds negative halves toward +Infinity: -0.125 becomes -0.12', () => {
    expect(computeTotal({ items: [{ price: -0.125, qty: 1 }] })).toBe(-0.12);
  });

  it('rounds 1.005 and 2.675 down because of their binary representation', () => {
    expect(computeTotal({ items: [{ price: 1.005, qty: 1 }] })).toBe(1);
    expect(computeTotal({ items: [{ price: 2.675, qty: 1 }] })).toBe(2.67);
  });

  it('rounds each line before summing: two 0.125 lines total 0.26, not 0.25', () => {
    const order = { items: [{ price: 0.125, qty: 1 }, { price: 0.125, qty: 1 }] };
    expect(computeTotal(order)).toBe(0.26);
  });

  it('rounds away float dust in the final sum: 0.1 + 0.2 totals 0.3', () => {
    const order = { items: [{ price: 0.1, qty: 1 }, { price: 0.2, qty: 1 }] };
    expect(computeTotal(order)).toBe(0.3);
  });

  it('multiplies price by qty before rounding the line', () => {
    const order = { items: [{ price: 9.99, qty: 2 }, { price: 0.99, qty: 1 }] };
    expect(computeTotal(order)).toBe(20.97);
  });
});

describe('computeTotal validation', () => {
  it('returns 0 for missing, non-array, or empty items', () => {
    expect(computeTotal({} as Order)).toBe(0);
    expect(computeTotal({ items: 'nope' } as unknown as Order)).toBe(0);
    expect(computeTotal({ items: [] })).toBe(0);
  });

  it('zeroes the whole order when any item is invalid', () => {
    const order = {
      items: [
        { price: 5, qty: 1 },
        { price: '5', qty: 1 },
      ],
    } as unknown as Order;
    expect(computeTotal(order)).toBe(0);
  });

  it('rejects a missing qty but coerces a string qty', () => {
    expect(computeTotal({ items: [{ price: 5 }] } as unknown as Order)).toBe(0);
    expect(computeTotal({ items: [{ price: 5, qty: '2' }] } as unknown as Order)).toBe(10);
  });
});

describe('summarize', () => {
  it('combines total, discount, and savings', () => {
    const result = summarize({ items: [{ price: 19.99, qty: 1 }] }, 'SAVE10');
    expect(result).toEqual({
      status: 'success',
      ok: true,
      total: 19.99,
      discounted: 17.99,
      itemCount: 1,
      savings: 2,
    });
  });

  it('reports zero savings for an unknown code', () => {
    const result = summarize({ items: [{ price: 10, qty: 3 }] }, 'BOGUS');
    expect(result.total).toBe(30);
    expect(result.discounted).toBe(30);
    expect(result.savings).toBe(0);
    expect(result.itemCount).toBe(1);
  });
});

types.ts

export interface Item {
  price: number;
  qty: number;
}

export interface Order {
  items: Item[];
}

export interface Result {
  status: string;
  ok: boolean;
  total: number;
  discounted: number;
  itemCount: number;
  savings: number;
}

Explanation

The rewrite keeps the public API and all observable behavior — including the quirks — while stripping the AI scaffolding. Gone are the step-number narration comments, the manual index loops, the `as any` / `as unknown as` type laundering, and the `safeLineTotal` wrapper, which was just a pass-through around `computeLineTotal`. Validation is now a single type guard, the discount if/else chain is a `Map` lookup with a default multiplier of 1 (a `Map`, not a plain object, so keys like `'toString'` can't accidentally match prototype members — unknown codes still mean no discount), and `summarize` returns its object literal directly since the literal already satisfies `Result`. Behavior was preserved deliberately, not accidentally. Validation still runs as a full pass before any summing, so one bad item still zeroes the whole order; `for...of` is used instead of `every`/`reduce` because it visits sparse-array holes as `undefined`, exactly like the original index loop. The guard keeps the original acceptance rules: `price` must be a number, `qty` is only checked for presence (so a string like `'2'` still passes and is coerced by the multiplication), and a `null` element still throws on property access rather than failing cleanly — I documented that instead of silently "fixing" it. The try/catch in `lineTotal` looks like dead weight but is reachable (a `BigInt` or `Symbol` qty passes validation, then throws on multiplication, and the original swallowed that as 0), so it stays. `applyDiscount` still rounds even when no code is given, and `roundMoney` is untouched because its `Math.round` semantics — half toward +Infinity, plus binary-float quirks like `1.005 → 1` — are observable behavior. The tests pin down exactly those edges: known/unknown/empty/null/case-sensitive discount codes, rounding after discount, half-up rounding, negative halves, float-representation cases, per-line rounding before summing, and final-sum rounding, plus a compact validation group and the `summarize` shape. A minimal `types.ts` is included so everything compiles standalone — keep your existing one if it already defines these shapes.

Judge detail

No raw judge output is published for this item yet. When it is, it lands under results/raw/ and appears here verbatim; the rubric and protocol are already documented on the Methodology page.