✏️

Typstで共通テスト(センター試験)

2024/12/20に公開

みなさん、Typst使ってますかー?
いいですよねTypstって

ところで共通テストとかセンター試験を自分で作ってみたくないですか?作ってみたいですよね?そう、作ってみたいんです。

ということで、Typstで共通テストを作れそうな感じのものを作ってみました!

2024年実施 共通テスト数2B 第2問 (1)のみ
https://drive.google.com/file/d/14sONftz2A53eKsPqJxHGmd7rkbXJ2nL6/view?usp=sharing

本物:https://www.dnc.ac.jp/kyotsu/kakomondai/r6/r6_honshiken_mondai.html

共通テストの見た目的な特徴

共通テストやセンター試験の特徴といえば、マークする番号やカタカナが書かれた、そして細長い数字ですよね。

ということで、まずは一つずつ再現していきましょう!
なお、フォントはお手持ちのもので調整してください

箱を再現

共通テストでは解答欄の数学ではカタカナ、その他教科では数字が箱の中に書いてあります。今回は両方に対応するべく、解答欄の記号を文字列で逐一記入するようにします。また、選択式では二重枠になっているので、それも対応しましょう。

style.typ
#let ana(c) = {
  let len = c.len()/3
  let w = 3em
  if len > 3{
    w = 0.5em + (len)*1em
  }
  box(
    block([
      #set align(center+horizon)
      #set text(font:"MS PGothic", 8pt)
      #c
    ], fill:white,radius: 0pt, stroke: 1pt+black,width: w,height:5mm, spacing:1em),
    baseline: 0.4em,
    inset:(x:0.3em, y:0.2em)
  )
}

#let sana(c) = {
  let len = c.len()/3
  let w = 3em
  if len > 3{
    w = 0.5em + (len)*1em
  }
  box(
    block([
      #set align(center+horizon)
      #set text(lang:"ja", font: "TMincho-GT01", 8pt)
      #c
    ], fill:white,radius: 0pt, stroke: 0.2pt+black,width: w,height:5mm, spacing:1em),
    baseline: 0.4em,
    inset:(x:0.3em, y:0.2em)
  )
}

#let ana_select(c) = {
  let len = c.len()/3
  let w = 3em
  if len > 3{
    w = 0.5em + (len)*1em
  }
  box(
    block( 
      [
        #set align(center+horizon)
        #box(
          block(
            [
              #set align(center+horizon)
              #set text(font:"MS PGothic", 8pt)
              #c
            ], 
            fill:white,radius: 0pt, stroke: 0.2pt+black,width: w,height:4mm, spacing:1em
          ),
          inset:(x:0.3em)
        )
      ],
      fill:white,radius: 0pt, stroke: 1pt+black,width: w+1mm,height:5mm, spacing:1em,
    ),
    baseline:0.4em,
    inset:(x:0.3em, y:0.2em)
  )
}

#let sana_select(c) = {
  let len = c.len()/3
  let w = 3em
  if len > 3{
    w = 0.5em + (len)*1em
  }
  box(
    block( 
      [
        #set align(center+horizon)
        #box(
          block(
            [
              #set align(center+horizon)
              #set text(lang:"ja", font: "TMincho-GT01", 8pt)
              #c
            ], 
            fill:white,radius: 0pt, stroke: 0.2pt+black,width: w,height:4mm, spacing:1em
          ),
          inset:(x:0.3em)
        )
      ],
      fill:white,radius: 0pt, stroke: 0.2pt+black,width: w+1mm,height:5mm, spacing:1em,
    ),
    baseline: 0.4em,
    inset:(x:0.3em, y:0.2em)
  )
}

数学などで3桁以上を記入させる場合、枠が自動的に伸びます。

例1

$(#h(0.3em)#ana("ケ")#h(0.3em))/#ana("コ")$

例2 (2023年 数2B 第3問(2))

$
  p_k=P(25<=U_k<=25+k)=P(-#ana_select("タ")/sqrt(50+k)<=Y<= #sana_select("タ")/sqrt(50+k))
$

数字を再現

数字の枠の楕円はSVGデータ(oval.svg)として作成しておきましょう。32*42px, 幅3pxでいい感じかと思います。

#let mark(n) = {
  set text(font:"MS PGothic", 8pt)
  [#box(height:1.2em, move(dy:0.25em, image("oval.svg")))#box(move(dx:-0.7em, dy:-0.0em,[#n]))#h(-0.5em)]
}

SVGを書いて、数字を楕円の中に移動させてる感じです。移動量などは適宜調整してください。

#move(dx:4em, block(box(inset:(x:1em, y:0.5em), [#set par(first-line-indent:0em, hanging-indent: 0em, leading: 1em)
  #mark(0)#h(1em)$S(3)$\
  #mark(1)#h(1em)2点$(2, S(2))$,$(4, S(4))$を通る直線の傾き\
  #mark(2)#h(1em)2点$(0, 0)$,$(3, S(3))$を通る直線の傾き\
  #mark(3)#h(1em)関数$y=S(x)$のグラフ上の点$(3, S(3))$における接線の傾き\
  #mark(4)#h(1em)関数$y=f(x)$のグラフ上の点$(3, f(3))$における接線の傾き\
]), stroke: 0.2pt+black, radius: 0pt, width: 90%))

中身をグレーで塗りつぶしたSVGも用意しておけば、マークした数字も再現できます。

まだ厳しいところ

重要な部分はこれで再現出来ました。ただし、まだ厳しいところはあります。

文中の式

文中の式もおおむねいけますが、積分や分数などの縦に幅をとるやつは、1行分のサイズに収められてしまうので、どうしてもおかしくなってしまいます。

typst 実物

インデント

単純に知識不足の可能性もありますが、(1)や(i)などだんだん入れ子にするうちにインデントをする必要がありますが、これがなかなか複雑でうまくいきませんでした。全行頭に#h(5em)などとしてやればできますけど、だるいだけですよね...

下付き文字

社会とかで下線引くときに、下線に➀やaなどの記号を付けますけど、typstってなにもないところに下付き文字を付けれないんですよね確か。#move使えばできるのかな...?未検証

文献が少ない

共通テストに限ったことではないですが、まだまだ文献が少ないです。公式ドキュメントはもちろん、githubのissueまで探しても見当たらない、あったけど実装されてなかったり仕様だったり...

最後に

再現できたところ、まだ難しいところ両方挙げましたけど、オリジナルの内容を再現するとかなら十分対応できると思います。皆さんも良き共通テスト再現ライフを~

Discussion