マークリーダーを使うプログラムいくつかあるのですが、すべて「マーク処理」の部分と、「採点処理」の部分の2つに分けてあります。これは制作の都合ですが、解や配点を変更した時もマークシートリーダを動かすことなく採点をし直すことができます。
ここでは各処理の分け方と選択のさせ方を説明します。
他人に解説するというより、自分が昔作ったプログラムを読み解くという比重が多くなります。
プログラムを読み解くと合理的でない部分や無駄に見える部分が必ず出てきます。直してすっきりする場合もありますが、動かなくなる場合や不具合が生ずる場合もあります。「ちゃんと動いているものは触るな」という原則はもっともです。
しかし、移植のために触ってしまいましたし、ゆくゆくはJavaなど別の言語にする計画もあって内容を把握する必要があります。
そんな訳でここからは自分の書いたものを読みといてそのまま記録することになりますが、それをここで直すのか否か、直したものだけを書くのかもその場その場で判断して行くことになるかと思います。
当初からマークリーダーから読んで正解、配点、各生徒の解答の並んだ解答一覧ファイルにする「マーク処理」の部分と、解答一覧ファイルから読んで採点したり統計を取ったりする「採点処理」の部分の2段階のシステムにしてあります。こうしておけば「採点処理」のプログラムはマークシートリーダを動かすことなく開発できますし、正解や配点を変更した時もファイルを訂正すれば、すぐに採点をし直すことができます。
処理の流れです。

プログラム実行時の処理の選択です。ここでファイルといっているのはすべて解答一覧ファイルです。
1:マークリーダ 2:最新ファイル 3:過去のファイル 4:終了 (5:TEST)の選択 3:の時 ファイル番号をセット 2:の時 最新のファイル番号をセット 1:の時 マークリーダから読み取ってファイルへ書き込み 指定ファイルからの採点処理
3:過去のファイルの処理

2:最新ファイルの処理

1:マークリーダからの一連の処理(マーク処理プログラムが終わると引き続き最新ファイルの採点処理に入る)

TESTとは前半のマークリーダー必須の部分でマークリーダではなくファイルからデータを読む開発用のモード。メニューから隠してある。
*INPSEL
GOSUB *FDCHK'o(DFNEXT$:outnext,DFLAST$:lastfile with E$/DFNAM$ no E$)
PRINT "登録データファイル数 ";VAL(MID$(DFLAST$,5,4)):PRINT
INDVMIN=1
do
IF TEST THEN PRINT "1_:テスト ";
IF NOT TEST THEN PRINT "1_:マークリーダ ";
PRINT "2:最新ファイル 3:過去のファイル 4:終了 (1_/2/3/4/5) ";
INPUT "",s$
IF s$="" THEN s$="1"
INDV=val(s$)
if indv=5 then TEST=NOT TEST
loop while INDV>4 OR INDV<INDVMIN
IF INDV=4 THEN end
PRINT:PRINT
IF VAL(MID$(DFLAST$,5,4))=0 AND (INDV=2 OR INDV=3) THEN *INPSEL
IF INDV=3 THEN '------ 過去のファイル ------
do
PRINT :INPUT "ファイル番号を入力してください ",I
MID$(DFNAM$,5,4)=RIGHT$("0000"+MID$(STR$(I),2),4)
DFLNAME$ =DFNAM$+E$
ERRCD=0:ON ERROR GOTO *GETERR
OPEN DDRD$+DFLNAME$ FOR INPUT AS #1
if errcd<>0 then continue
LINE INPUT #1,CDID$: LINE INPUT #1,COMM$
CLOSE #1
ON ERROR GOTO 0
IF COMM$<>"" THEN comm$="ありません"
PRINT:COLOR 5:PRINT "ファイルのメモ : ";:COLOR 7:PRINT COMM$
COLOR 5:PRINT " このファイルでよろしいですか (Y_,N)";:COLOR 7
INPUT "" ,I$
if i$="" then i$="Y"
GOSUB *CAPI
loop while I$<>"Y"
else IF INDV=2 THEN '------ 最新ファイル ------
DFLNAME$ =DFLAST$
else IF INDV=1 THEN '------ マークリーダー ------
COLOR 5
PRINT:PRINT "ファイル番号 ";VAL(MID$(DFNEXT$,5,4))
IF COMM$<>"" THEN DM$="おなじでよければ" ELSE DM$="なければ"
IF COMM$<>"" THEN PRINT:PRINT "現在のメモは ";:COLOR 7:PRINT COMM$;
IF COMM$<>"" THEN COLOR 5:PRINT " です."
PRINT:PRINT "メモが必要なら入れて下さい (";DM$;" リターンのみ)"
COLOR 7:INPUT "",DM$
IF DM$<>"" THEN COMM$=DM$
do
JPMX=0:ERASE FLG,HSTA,CHK
DIM FLG(MLIM),HSTA(MLIM,KALIM),CHK(IDLIM)
GOSUB *GSEIN :GOSUB *GHAIN: JFON=FALSE
IF EHS$="J" THEN
GOSUB *SETJF
GOSUB *GHAIN:JFON=TRUE
endif
GOSUB *SETKZ
'DM$=INPUT$(1)
LPT=FALSE:GOSUB *GSEHACHK :COLOR 5
PRINT CR$;" G_:答案読込開始 R:正解の読み込みからやりなおす";
PRINT " B:最初からやりなおす ";
COLOR 7:INPUT "",I$:IF I$="" THEN I$="G"
GOSUB *CAPI
IF I$="R" THEN CLOSE
IF I$="B" THEN CLOSE :GOTO *BGN
loop until i$="G"
DEPTY=FALSE: CDMX=0 : GCC=0:GACR=0:GAC4=0
WHILE NOT DEPTY
CDMX=CDMX+1
GOSUB *GKAIN
IF GPEND OR DEPTY THEN GOSUB *GRPMSG: GCC=0:GACR=0:GAC4=0
WEND:CDMX=CDMX-1
DFLAST$=DFNEXT$ :CLOSE
M=INSTR(DFLAST$,"."):DFNAM$=LEFT$(DFLAST$,M-1)
OPEN DDRD$+LASTFN$ FOR create AS #1
PRINT #1,MID$(DFLAST$,5,4):CLOSE #1
PRINT :COLOR 6:PRINT REMARK$;:GOSUB *WKY:PRINT :COLOR 7
IF I$=CHR$(27) THEN *ENDJOB
DFLNAME$ =DFLAST$
endif
やはり人間とのやり取りに手間がかかっています。この色のサブルーチンが本質的な処理をしています。
このあと指定ファイルからの採点処理があります。
やはりこの色のサブルーチンが本質的な処理をしていて、マーク処理の作業と対応しています。
*EXEOUTJOB '------ 指定ファイルからの採点処理 ------ GOSUB *SEIN JPMX=0:ERASE FLG,HSTA,CHK DIM FLG(MLIM),HSTA(MLIM,KALIM),CHK(IDLIM) GOSUB *HAIN: JFON=FALSE IF EHS$="J" THEN GOSUB *SETJF:GOSUB *HAIN:JFON=TRUE GOSUB *SETKZ GOSUB *SEHACHK PRINT :COLOR 5:PRINT "採点の処理をします":COLOR 7 OPEN DDRD$+DFNAM$+".TXT" FOR create AS #1 GOSUB *SHORI GOSUB *MEAN CLOSE #1 GOSUB *SORTH PRINT :PRINT :COLOR 4:PRINT "解答分布の処理をします":COLOR 7 OPEN DDRD$+DFNAM$+"HIS1.TXT" FOR create AS #1 GOSUB *OUTHIS CLOSE #1 OPEN DDRD$+DFNAM$+"HIS2.TXT" FOR create AS #1 GOSUB *OUTHISFLE CLOSE #1 *ENDJOB PRINT:PRINT:PRINT "ひとつの作業が終了しました (BGN)":PRINT:PRINT CLOSE:WHILE INKEY$<>"":WEND GOTO *BGN
なつかしいgoto文が残っています。「A4マークリーダー用採点システム」などとタイトルを表示して *INPSEL に流れていく部分です。プログラムの構造化に努めていた頃ですが、BASICでは苦しいところもありました。ここはそれなりにわかりやすいgoto文です。