ClassItem::ClashType ClassItem::clashWith(ClassItem *other) { qfLogFuncFrame() << data().className() << "vs" << other->data().className(); auto dt = data(); auto odt = other->data(); int t1 = dt.startTimeMin(); int t2 = t1 + durationMin(); int ot1 = odt.startTimeMin(); int ot2 = ot1 + other->durationMin(); if(ot1 < t2 && ot2 > t1) { // overlap if(dt.courseId() == odt.courseId()) { qfDebug() << "\t ret: CourseOverlap"; return ClashType::CourseOverlap; } if(dt.firstCode() == odt.firstCode()) { int si = dt.startIntervalMin(); int osi = odt.startIntervalMin(); if(si > 0 && osi > 0) { int si_gcd = gcd(si, osi); if((t1 % si_gcd) == (ot1 % si_gcd)) { qfDebug() << "\t ret: 2RunnersOverlap"; return ClashType::RunnersOverlap; } } } } qfDebug() << "\t ret: NONE"; return ClashType::None; }
void ClassItem::updateToolTip() { auto dt = data(); QString tool_tip; // HTML tooltip can cause word wrap tool_tip = "<html><body>"; tool_tip += tr("class: <b>%1</b>, %2 runners + %3 vacants<br/>").arg(dt.className()).arg(dt.runsCount()).arg(runsAndVacantCount() - dt.runsCount()); tool_tip += tr("first code <b>%1</b>, course %2 - %3<br/>").arg(dt.firstCode()).arg(dt.courseId()).arg(dt.courseName()); tool_tip += tr("vacants before: %1, every: %2, after: %3<br/>").arg(dt.vacantsBefore()).arg(dt.vacantEvery()).arg(dt.vacantsAfter()); tool_tip += tr("class start: %1, interval: %2, duration: %3, end: %4<br/>").arg(dt.startTimeMin()).arg(dt.startIntervalMin()).arg(durationMin()).arg(dt.startTimeMin() + durationMin()); tool_tip += tr("map count: %1").arg(dt.mapCount()); //if(dt.minStartTimeSec() != ClassData::INVALID_START_TIME_SEC || dt.maxStartTimeSec() != ClassData::INVALID_START_TIME_SEC) { // tool_tip += tr("competitors start first: %1, last: %2<br/>").arg(dt.minStartTimeSec() / 60).arg(dt.maxStartTimeSec() / 60); //} auto clst = clashingClasses(); if(clst.count()) { QStringList sl; for(auto *cl : clst) { sl << cl->data().className(); } tool_tip += tr("clash with: %1<br/>").arg(sl.join(", ")); } tool_tip += "</body></html>"; tool_tip.replace(' ', " "); setToolTip(tool_tip); }
int endline_of_If(int line) /* if 문에 대응하는 end 위치 */ { CodeSet cd; char *save = code_ptr; cd = firstCode(line); for (;;) { line = cd.jmpAdrs; cd = firstCode(line); if (cd.kind==Elif || cd.kind==Else) continue; if (cd.kind == End) break; } code_ptr = save; return line; }
QColor ClassItem::color() const { auto dt = data(); int hue = dt.firstCode() % 100; QColor c; c.setHsvF(hue / 100., 1, 1); return c; }
void syntaxChk() /* 구문 검사 */ { syntaxChk_mode = true; for (Pc=1; Pc<(int)intercode.size(); Pc++) { code = firstCode(Pc); switch (code.kind) { case Func: case Option: case Var: /* 검사 완료 */ break; case Else: case End: case Exit: code = nextCode(); chk_EofLine(); break; case If: case Elif: case While: code = nextCode(); (void)get_expression(0, EofLine); /* 식값 */ break; case For: code = nextCode(); (void)get_memAdrs(code); /* 제어 변수 주소 */ (void)get_expression('=', 0); /* 초깃값 */ (void)get_expression(To, 0); /* 최종값 */ if (code.kind == Step) (void)get_expression(Step,0); /* 증분값 */ chk_EofLine(); break; case Fcall: /* 대입 없는 함수 호출 */ fncCall_syntax(code.symNbr); chk_EofLine(); (void)stk.pop(); /* 반환 값 불필요 */ break; case Print: case Println: sysFncExec_syntax(code.kind); break; case Gvar: case Lvar: /* 대입문 */ (void)get_memAdrs(code); /* 좌변 주소 */ (void)get_expression('=', EofLine); /* 우변식 값 */ break; case Return: code = nextCode(); /* 반환 값 */ if (code.kind!='?' && code.kind!=EofLine) (void)get_expression(); if (code.kind == '?') (void)get_expression('?', 0); chk_EofLine(); break; case Break: code = nextCode(); if (code.kind == '?') (void)get_expression('?', 0); chk_EofLine(); break; case EofLine: break; default: err_exit("잘못된 기술입니다: ", kind_to_s(code.kind)); } } syntaxChk_mode = false; }
void fncExec(int fncNbr) /* 함수 실행 */ { // 함수입구처리1 int save_Pc = Pc; /* 현재 실행행을 저장 */ int save_baseReg = baseReg; /* 현재 baseReg를 저장 */ int save_spReg = spReg; /* 현재 spReg를 저장 */ char *save_code_ptr = code_ptr; /* 현재 실행행 분석용 포인터를 저장 */ CodeSet save_code = code; /* 현재 code를 저장 */ // 함수입구처리2 Pc = Gtable[fncNbr].adrs; /* 새로운 Pc 설정 */ baseReg = spReg; /* 새로운 베이스 레지스터 설정 */ spReg += Gtable[fncNbr].frame; /* 프레임 확보 */ Dmem.auto_resize(spReg); /* 메모리 유효 영역 확보 */ returnValue = 1.0; /* 반환 값의 기본값 */ code = firstCode(Pc); /* 시작 코드 획득 */ // 인수 저장 처리 nextCode(); code = nextCode(); /* Func ( 건너뜀 */ if (code.kind != ')') { /* 인수 있음 */ for (;; code=nextCode()) { set_dtTyp(code, DBL_T); /* 대입 시 형 확정 */ Dmem.set(get_memAdrs(code), stk.pop()); /* 실인수 값 저장 */ if (code.kind != ',') break; /* 인수 종료 */ } } code = nextCode(); /* ) 건너뜀 */ // 함수 본체 처리 ++Pc; block(); return_Flg = false; /* 함수 본체 처리 */ // 함수 출구 처리 stk.push(returnValue); /* 반환 값 설정 */ Pc = save_Pc; /* 호출 전 환경을 복원 */ baseReg = save_baseReg; spReg = save_spReg; code_ptr = save_code_ptr; code = save_code; }
void statement() /* 문 */ { CodeSet save; int top_line, end_line, varAdrs; double wkVal, endDt, stepDt; if (Pc>maxLine || exit_Flg) return; /* 프로그램 종료 */ code = save = firstCode(Pc); top_line = Pc; end_line = code.jmpAdrs; /* 제어 범위의 시작과 끝 */ if (code.kind == If ) end_line = endline_of_If(Pc); /* if문일 때의 끝 */ switch (code.kind) { case If: // if if (get_expression(If, 0)) { /* 참(TRUE)이면 */ ++Pc; block(); Pc = end_line + 1; /* 실행하고 */ return; /* 종료 */ } Pc = save.jmpAdrs; /* 다음으로 */ // elif while (lookCode(Pc) == Elif) { save = firstCode(Pc); code = nextCode(); if (get_expression()) { /* 참(TRUE)이면 */ ++Pc; block(); Pc = end_line + 1; /* 실행하고 */ return; /* 종료 */ } Pc = save.jmpAdrs; /* 다음으로 */ } // else if (lookCode(Pc) == Else) { /* else를 */ ++Pc; block(); Pc = end_line + 1; /* 실행하고 */ return; /* 종료 */ } // end ++Pc; break; case While: for (;;) { /* */ if (!get_expression(While, 0)) break; /* false 종료 */ ++Pc; block(); /* [실행] */ if (break_Flg || return_Flg || exit_Flg) { /* */ break_Flg = false; break; /* 중단 */ } /* */ Pc = top_line; code = firstCode(Pc); /* 맨 앞으로 */ } /* */ Pc = end_line + 1; /* */ break; case For: /* for 제어변수, 초깃값, 최종값, 증분식 */ save = nextCode(); varAdrs = get_memAdrs(save); /* 제이변수 주소 구하기 */ expression('=', 0); /* 초깃값 */ set_dtTyp(save, DBL_T); /* 형 확정 */ Dmem.set(varAdrs, stk.pop()); /* 초깃값을 설정 */ endDt = get_expression(To, 0); /* 최종값을 보존 */ /* 증분값을 보존 */ if (code.kind == Step) stepDt = get_expression(Step, 0); else stepDt = 1.0; for (;; Pc=top_line) { /* */ if (stepDt >= 0) { /* 증가 루프 */ if (Dmem.get(varAdrs) > endDt) break; /* 거짓이면 종료 */ } else { /* 감소 루프 */ if (Dmem.get(varAdrs) < endDt) break; /* 거짓이면 종료 */ } /* */ ++Pc; block(); /* [ 실행 ] */ if (break_Flg || return_Flg || exit_Flg) { /* */ break_Flg = false; break; /* 중단 */ } /* */ Dmem.add(varAdrs, stepDt); /* 값 갱신 */ } /* */ Pc = end_line + 1; /* */ break; case Fcall: /* 대입이 없는 함수 호출 */ fncCall(code.symNbr); (void)stk.pop(); /* 반환 값 불필요 */ ++Pc; break; case Func: /* 함수 정의는 건너뀜 */ Pc = end_line + 1; break; case Print: case Println: sysFncExec(code.kind); ++Pc; break; case Gvar: case Lvar: /* 대입문 */ varAdrs = get_memAdrs(code); expression('=', 0); set_dtTyp(save, DBL_T); /* 대입할 때 형 확정*/ Dmem.set(varAdrs, stk.pop()); ++Pc; break; case Return: wkVal = returnValue; code = nextCode(); if (code.kind!='?' && code.kind!=EofLine) /* '식'이 있으면 반환 값을 계산 */ wkVal = get_expression(); post_if_set(return_Flg); /* ?가 있으면 처리 */ if (return_Flg) returnValue = wkVal; if (!return_Flg) ++Pc; break; case Break: code = nextCode(); post_if_set(break_Flg); /* ? 가 있으면 처리 */ if (!break_Flg) ++Pc; break; case Exit: code = nextCode(); exit_Flg = true; break; case Option: case Var: case EofLine: /* 실행 시는 무시 */ ++Pc; break; default: err_exit("잘못된 기술입니다: ", kind_to_s(code.kind)); } }