// 달시장 자료. 품목, 손님 종류와 성향, 시드에서 손님을 뽑는 결정론 난수를 둡니다.
// 손님 하나는 시드 숫자, 밤, 차례 세 정수에서 나오며 종류, 원하는 품목, 예산, 성향을 가집니다.
// 같은 시드와 밤이면 늘 같은 손님 줄이 나옵니다. 난수는 비트 연산 없이 정수 산술만 씁니다.
// 상태를 들거나 바꾸지 않습니다.
// moon-market data: goods, customer kinds and traits, and the seeded customer generator.

export type 품목 = "떡" | "어묵" | "차"
export type 손님종류 = "학생" | "직장인" | "아주머니"
export type 손님성향 = "알뜰" | "급함" | "묶음"
export record 손님 { 종류: 손님종류, 원함: 품목, 예산: int, 성향: 손님성향 }

let 품목들: Array<품목> = ["떡", "어묵", "차"]
let 종류들: Array<손님종류> = ["학생", "직장인", "아주머니"]
let 성향들: Array<손님성향> = ["알뜰", "급함", "묶음"]

// 공용 도우미 시작 내보내기 (djb2해시 선형합동다음)
// 여러 도구가 같은 원본을 씁니다. 여기서 고치지 않고 원본에서 고친 뒤 다시 생성합니다.

// 5381 에서 시작해 글자마다 33 을 곱해 더하는 djb2 해시입니다. 2147483647 로 나눈 나머지만 들고 가므로 int 범위를 넘지 않습니다.
export function djb2해시(글: string) -> int {
  글.scalars().reduce(5381, (합, 글자) => (합 * 33 + (글자.codePointAt(0) ?? 0)) % 2147483647)
}

// 곱수 1103515245, 증분 12345, 법 2^31 의 선형 합동입니다. 값이 2^31 미만이면 곱이 64비트를 넘지 않고, 음수는 [0, 2^31) 로 옮깁니다.
export function 선형합동다음(값: int) -> int {
  let 다음 = (1103515245 * 값 + 12345) % 2147483648
  if 다음 < 0 { 다음 + 2147483648 } else { 다음 }
}

// 공용 도우미 끝

export function 품목목록() -> Array<품목> { 품목들 }

function 난수열(시작: int, 개수: int) -> Array<int> {
  let mut 수들: Array<int> = [선형합동다음(시작)]
  while 수들.length < 개수 { 수들.push(선형합동다음(수들[수들.length - 1])) }
  수들
}

// 넷째 난수는 쓰지 않지만 뽑아 두어야 성향이 저장된 밤들과 같게 나옵니다.
export function 손님생성(시드수: int, 밤: int, 차례: int) -> 손님 {
  let 난수 = 난수열(시드수 + 밤 * 7919 + 차례 * 104729 + 1, 5)
  손님 {
    종류: 종류들[난수[0] % 3],
    원함: 품목들[난수[1] % 3],
    예산: 8 + (난수[2] % 12),
    성향: 성향들[난수[4] % 3],
  }
}
