import gradio as gr # 질문 및 선택지 설정 questions = ["1. 비증권성으로 판단받은 법률자문 검토서를 보유하고 있나요?", "2. TOP 10 Holder 배분율을 선택해주세요(TOP 10 Holder)가 얼마나 보유하고 있나요?)", "3. 토큰 발행을 한 이후 얼마나 지났습니까?", "4. 프로젝트 공시관련 규정(or 매뉴얼)이 있습니다", "5. 자체 운영 커뮤니티 포함 다양한 채널에 각종 이슈, 공지, 공시 등 실시간 반영하고 있습니까?", "6. 비즈니스 관련 법률 이슈 해결을 위한 준비상태를 선택해 주세요. ", "7. 프로젝트에서 운영중인 커뮤니티(서비스 가입자 포함) 인원 총 합을 선택해 주세요. ", "8. 프로젝트 홍보를 위한 뉴스, 언론 등 미디어 노출 여부를 선택해 주세요", "9. 밋업 등 마케팅 실적을 선택해 주세요", "10. 어드바이저 또는 파트너의 전문성 수준을 선택해 주세요 ", "11. 프로젝트와 연동된 전자지갑 서비스가 있습니까? ", "12. 멀티체인 지원의 정도를 선택해주세요 ", "13. GitHub에 프로젝트를 공개하고 활동하고 있나요?", "14. 프로젝트와 관련된 기술 및 비즈니스 관련 특허를 가지고 있습니까?", "15. 기술 인력(in-house)중 관련 부분 박사 또는 기술자 자격 보유자가 있나요?", "16. 플랫폼/서비스 운용기간이 어떻게 되나요?", "17. 보안 기술 감사 기관의 보안감사서(Audit)를 보유하고 있나요? ", "18. 보안감사서가 외부에 공개되어 있습니까? ", "19. 보안메뉴얼에 따른 정기적인 취약점 점검 활동을 하고 있습니까? ", "20. 버그바운티 서비스를 했거나 현재 하고 있습니까? ", "21. 개인정보보호조치 수준을 선택해주세요 ", "22. 코인마켓캡 또는 코인게코에서 조회된 온체인 데이터 시총 순위 선택해주세요", "23. 상장 거래소가 있을 경우 상장가 대비 현재 시세를 선택해 주세요", "24. 상장되어 있는 거래소를 선택해주세요", "25. 지난 52주 기준 온체인 챠트상 트랜잭션 추세를 선택해주세요", "26. 플랫폼 이용자 총량, (플랫폼 이용자 수 + )온체인 홀더 수(=지갑수)을 선택해주세요 ", "27. 로드맵 및 히스토리 공개 수준을 선택해주세요 ", "28. 로드맵 달성 수준을 선택해주세요 ", "29. 재단 및 운영사(지배구조 포함)의 형태를 선택해 주세요", "30. 경영진을 포함한 핵심인력의 전문성 또는 영향력 수준을 선택해주세요 ", "31. Cash runway(재단의 현금유동성 또는 재무건전성을 기준으로 사업지속 가능기간)는 어떻게 되나요?", "32. 토큰 유통관련 투자자 보호를 위한 준비상태를 선택해주세요." ] options = [["네", "아니오"], ["30% 이하", "31~69%이하", "70% 이상"], ["2년 이상", "1년 미만", "6개월 미만"], ["네", "아니오"], ["네", "아니오"], ["준법관리팀(변호사 고용) 보유(선택)", "준법프로세스 및 자체 메뉴얼 보유 또는 정기적으로 법률자문을 받고 있음(선택)", "법률자문을 받은 이력 있음(선택)", "없음"], ["커뮤니티 인원수 합 5만 이상", "커뮤니티 인원수 합 1만 이상", "커뮤니티 인원수 합 1천 이상","커뮤니티 인원수 합 1천 이하"], ["글로벌 상위 언론 및 미디어 뉴스에 노출되었습니다", "국내 대형 언론 및 미디어 뉴스에 노출되있습니다", "국내 중소형 일반 언론 보도자료에 노출되었습니다","노출되지 않습니다"], ["지속적이고 정기적인 온오프 마케팅 진행 ","간헐적 마케팅 실행 수준: 밋업포함 온오프 마케팅 진행","마케팅 실행 이력없음"], ["글로벌 수준","로컬 탑 수준","로컬 일반 수준"], ["자체개발한 지갑을 보유하고 있으며 서비스 중입니다 ","외부개발한 지갑을 보유하고 있으며 서비스 중입니다 ","지갑 서비스를 하고 있지 않습니다"], ["복수(3종 이상) 체인을 지원하고 지원 API 또는 브릿지가 공개되어 있습니다 ","복수(2종 이상) 체인을 지원 및 브릿지가 연결되어 있습니다","단일 체인만 지원합니다"], ["네 ", "아니오"], ["등록 완료된 특허를 보유하고 있습니다 ","특허를 받는 절차를 진행중입니다 (출원 중)", "없음"], ["경력 프로필 기준 박사 및 기술사 자격 인력이 있습니다.", "박사급은 아니지만 석사급 수준, 관련 경력 10년 이상의 경력자가 있습니다","관련분야 경력 10년 미만의 일반적인 수준의 경력자가 있습니다"], ["플랫폼/서비스 운용기간이 1년 이상 입니다 ","플랫폼/서비스 운용기간이 1년 미만 입니다","플랫폼/서비스 운용기간이 6개월 미만 입니다"], ["글로벌TOP 수준.슬로우미스트/써틱 등 상위30% 기관을 통한 평가를 받았습니다 ","일반수준의 보안감사기관을 통한 평가를 받았습니다","보안감사서가 없습니다."], ["보안감사업체 홈페이지, 코인마켓갭 등 사이트에서 확인 가능합니다 ","공개되어 있지 않습니다"], ["네 ","아니오"], ["네 ", "아니오"], ["내부 직원 중 CISO 등록된 임원이 있다 ","내부 직원 중 개인정보보호를 위한 관리자가 있다", "없음"], ["온체인 데이터 정량화된 지표에서 시총상위 500위 이내인가?(선택) ","온체인 데이터 정량화된정량화된 지표에서 시총상위 500위 이상 1,000위 미만인가?(선택)","온체인 데이터 정량화된 지표에서 시총상위 1,000위 이상 5,000위 미만인가?(선택)","온체인 데이터 정량화된 지표에서 시총상위 5,000위 초과(또는 미표시)인가?(선택)","코인마켓갭, 코인게코 외 다른 곳(DEX 포함)에서 온체인 데이터 시총 순위를 확인할수 있습니다","없음"], ["상장가 기준 31% 이상 상승 유지(거래소복수시 최대거래량 거래소 기준) ","상장가 기준 -30~+30% 유지(거래소복수시 최대거래량 거래소 기준)","상장가 기준 -31% 이상 하락(거래소복수시 최대거래량 거래소 기준)"], ["선물/영구 마켓에 등록되어 있습니다 ","FIAT 마켓(1개 기준) 포함 10개 미만의 현물 마켓에 등록되어 있습니다","중앙화 거래소에 등록되어 있습니다","DEX 거래소에 등록되어 있습니다"], ["지난 52주간 상승추세의 흐름을 보이고 있습니다 ","지난 52주간 일정한 수준의 흐름을 보이고 있습니다","지난 52주간 하락추세의 흐름을 보이고 있습니다"], ["100,000 이상입니다 ","50,000 이상 100,000 미만입니다","10,000 이상 50,000 미만입니다","1,000 이상 10,000명 미만입니다","1,000 미만입니다"], ["코인마켓캡 또는 코인게코 등에 공개하고 있습니다 ","자체커뮤니티에 히스토리를 공개하고 있습니다","홈페이지 또는 백서에서만 히스토리를 공개하고 있습니다"], ["마일스톤 달성 70% 이상을 달성 중입니다 ","마일스톤 달성 20% 이상 70% 미만을 달성 중입니다","마일스톤 달성 20% 미만을 달성 중입니다"], ["재단 및 운용사(지배구조 포함)이 IPO(상장) 법인 ","재단 및 운용사(지배구조 포함)이 외감 또는 법률 등록(예, 전자금융업자, VASP 등)법인","재단 및 운용사(지배구조 포함)이 일반 법인"], ["글로벌 수준의 뛰어난 전문성과 영향력을 가지고 있습니다 ","로컬 수준의 전문성과 영향력을 가지고 있습니다"], ["1년 이상 ","1년 이내","6개월 이내"], ["외부 예치(커스터디) 적용 & 재단 락업 스테이킹 & 빅홀더 락업 스테이킹", "재단 락업 & 빅홀더 락업 스테이킹을 하고 있습니다", "재단 락업 또는 빅홀더 락업 스테이킹민 하고 있습니다", "해당사항 없습니다"] ] scores = [[1, 0], [3, 2, 1], [2, 1.5, 1], [1, 0], [1, 0], [3, 2, 1, 0], [3, 2, 1, 0], [3, 2, 1, 0], [2, 1, 0], [3, 2, 1], [2, 1, 0], [3, 2, 1], [1, 0], [2, 1, 0], [3, 2, 1], [2, 1, 0], [2, 1, 0], [1, 0], [1, 0], [1, 0], [2, 1, 0], [3, 2.5, 2, 1.5, 1, 0], [3, 2, 1], [4, 3, 2, 1], [1, 0.5, 0], [5, 4, 3, 2, 1], [1.5, 1, 0.5], [1.5, 1, 0.5], [3, 2, 1], [2, 1], [3, 2, 1], [3, 2, 1, 0] ] def calculate_score(*answers): total_score = sum([scores[i][options[i].index(answer)] for i, answer in enumerate(answers)]) grade, definition = get_grade(total_score) # 등급과 정의를 얻기 위한 함수 호출 return total_score, grade, definition # 총점, 등급, 등급 정의를 반환 def get_grade(total_score): converted_score = (total_score) grades = { 'A': (65.7, 73, "등급정의: 매우 양호한 프로젝트 수행 역량과 진행을 보이고 있으며 향후 발전 가능성과 지속성 역시 높은 것으로 평가됩니다.대외적인 환경 변화에도 유연한 대응과 복원력을 보유하고 있는 것으로 판단됩니다."), 'B': (51.1, 65.6, "등급정의: 프로젝트 수행 역량과 진행이 업계 평균 수준으로 목표달성 능력이 있고 문제해결 능력이 있는 것으로 판단됩니다. 적절한 어드바이저와 역량 조성을 강화한다면 보다 발전적인 상황으로 프로젝트 수행이 가능할 것으로 판단됩니다."), 'C': (29.2, 51, "등급정의: 프로젝트의 기술적 타당성 및 비즈니스 모델평가에서 미흡한 효소가 존재합니다. 현재 프로젝트 수행은 가능하나 위험성이 존재합니다. 부족한 부분에 대한 보완과 컨설팅이 필요합니다."), 'D': (21.9, 29.1, "등급정의: 프로젝트의 시작은 가능하나 여러 위험 요소가 산재되어 있기에 수행이 사실상 불가능한 수준으로 판단됩니다. 보다 근본적인 검토가 필요할 것으로 판단됩니다. 상장을 위한 컨설팅이 반드시 필요합니다."), 'F': (0, 21.8, "등급정의: 프로젝트의 시작은 가능하나 여러 위험 요소가 산재되어 있기에 수행이 사실상 불가능한 수준으로 판단됩니다. 보다 근본적인 검토가 필요할 것으로 판단됩니다. 상장을 위한 컨설팅이 반드시 필요합니다.") } for grade, (low, high, definition) in grades.items(): if low <= converted_score <= high: return grade, definition # 등급과 정의를 함께 반환 return "No Grade", "" # 등급을 찾을 수 없는 경우 css = """ footer { visibility: hidden; } /* 버튼 스타일링 */ button { background: linear-gradient(135deg, #007BFF, #004085); border: none; color: white; padding: 10px 20px; text-align: center; display: inline-block; font-size: 16px; border-radius: 5px; cursor: pointer; transition: background 0.5s ease; } button:hover { background: linear-gradient(135deg, #0056b3, #002752); } /* 탭 색깔 변경을 위한 CSS */ /* 탭 버튼 스타일 */ .tab-container .tab { background-color: #f0f0f0; /* 연한 회색으로 배경색 변경 */ color: #333; /* 글자색 변경 */ } /* 선택된 탭 스타일 */ .tab-container .tab.selected { background-color: #d9d9d9; /* 선택된 탭의 배경색을 더 어두운 회색으로 변경 */ color: #000; /* 선택된 탭의 글자색을 검정색으로 변경 */ border-bottom: 2px solid #007BFF; /* 선택된 탭의 하단 테두리 스타일 */ } /* 탭 컨텐츠 영역 스타일 */ .tab-content { border: 1px solid #dcdcdc; /* 탭 컨텐츠 영역의 테두리 색상 */ background-color: #f9f9f9; /* 탭 컨텐츠 영역의 배경색 */ } /* 입력 폼 및 출력 폼 스타일링 */ .input, .output { box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); /* 입체감을 주는 그림자 추가 */ border: 2px solid #17a2b8; /* 컬러 테두리 적용 */ border-radius: 5px; /* 테두리 둥글게 */ } .input:hover, .output:hover { box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); /* 호버 시 더 큰 그림자 효과 */ } /* 타이틀과 설명글 가운데 정렬 추가 */ .markdown { text-align: center; /* 텍스트를 가운데 정렬 */ } /* 결과 출력 컴포넌트의 글자 크기 3배로 조정 */ .output { font-size: 300%; /* 기본 글자 크기의 2배 */ } /* 탭 클릭 시 눌린 탭에 적용될 스타일 */ .tab_button.selected { background-color: #007BFF; /* 선택된 탭의 배경색을 변경 */ color: white; /* 선택된 탭의 글자색을 변경 */ border-bottom: 2px solid #007BFF; /* 선택된 탭 하단에 테두리 추가 */ } """ with gr.Blocks(css=css) as demo: gr.Markdown("# 코레이팅(KORating) 셀프 진단 서비스", elem_id="title") # 타이틀 gr.Markdown("### 디지털자산 인증평가의 리더 '코레이팅'(KORating) 셀프 진단 서비스는, 투자자 보호 및 건전한 가상자산 생태계 구축을 지원합니다.", elem_id="description1") # 설명글 1 gr.Markdown("### 기본 정보 입력 후 총 8단계 TAP(1단계 ~ 최종 8단계까지) 클릭 후 입력 바랍니다.", elem_id="description2") # 설명글 2 with gr.Tab("진단 기본 정보 입력"): project_name = gr.Textbox(label="프로젝트명") contact_name = gr.Textbox(label="담당자 성명") contact_phone = gr.Textbox(label="연락처") contact_email = gr.Textbox(label="이메일 주소") with gr.Tab("1단계"): answer1 = gr.Radio(choices=options[0], label=questions[0]) answer2 = gr.Radio(choices=options[1], label=questions[1]) answer3 = gr.Radio(choices=options[2], label=questions[2]) answer4 = gr.Radio(choices=options[3], label=questions[3]) with gr.Tab("2단계"): answer5 = gr.Radio(choices=options[4], label=questions[4]) answer6 = gr.Radio(choices=options[5], label=questions[5]) answer7 = gr.Radio(choices=options[6], label=questions[6]) answer8 = gr.Radio(choices=options[7], label=questions[7]) with gr.Tab("3단계"): answer9 = gr.Radio(choices=options[8], label=questions[8]) answer10 = gr.Radio(choices=options[9], label=questions[9]) answer11 = gr.Radio(choices=options[10], label=questions[10]) answer12 = gr.Radio(choices=options[11], label=questions[11]) with gr.Tab("4단계"): answer13 = gr.Radio(choices=options[12], label=questions[12]) answer14 = gr.Radio(choices=options[13], label=questions[13]) answer15 = gr.Radio(choices=options[14], label=questions[14]) answer16 = gr.Radio(choices=options[15], label=questions[15]) with gr.Tab("5단계"): answer17 = gr.Radio(choices=options[16], label=questions[16]) answer18 = gr.Radio(choices=options[17], label=questions[17]) answer19 = gr.Radio(choices=options[18], label=questions[18]) answer20 = gr.Radio(choices=options[19], label=questions[19]) with gr.Tab("6단계"): answer21 = gr.Radio(choices=options[20], label=questions[20]) answer22 = gr.Radio(choices=options[21], label=questions[21]) answer23 = gr.Radio(choices=options[22], label=questions[22]) answer24 = gr.Radio(choices=options[23], label=questions[23]) with gr.Tab("7단계"): answer25 = gr.Radio(choices=options[24], label=questions[24]) answer26 = gr.Radio(choices=options[25], label=questions[25]) answer27 = gr.Radio(choices=options[26], label=questions[26]) answer28 = gr.Radio(choices=options[27], label=questions[27]) with gr.Tab("8단계/ 최종"): answer29 = gr.Radio(choices=options[28], label=questions[28]) answer30 = gr.Radio(choices=options[29], label=questions[29]) answer31 = gr.Radio(choices=options[30], label=questions[30]) answer32 = gr.Radio(choices=options[31], label=questions[31]) submit_btn = gr.Button("모든 입력 완료후 제출 버튼 클릭") score_output = gr.Number(label="총점(73점 만점)") grade_output = gr.Text(label="등급") definition_output = gr.Textbox(label="등급 정의") submit_btn.click( fn=calculate_score, inputs=[answer1, answer2, answer3, answer4, answer5, answer6, answer7, answer8, answer9, answer10, answer11, answer12, answer13, answer14, answer15, answer16, answer17, answer18, answer19, answer20, answer21, answer22, answer23, answer24, answer25, answer26, answer27, answer28, answer29, answer30, answer31, answer32], outputs=[score_output, grade_output, definition_output] ) demo.launch()