KIM-JINO5 4 tháng trước cách đây
mục cha
commit
5f5b9930cc

+ 100 - 10
Models/LottoModel.cs

@@ -1,5 +1,7 @@
-using System.Text;
+using System.Collections.Generic;
+using System.Text;
 using System.Text.Json;
+using System.Text.Json.Serialization;
 
 namespace economy.Models.Lotto
 {
@@ -13,6 +15,7 @@ namespace economy.Models.Lotto
         }
 
         // 로또 당첨 번호 조회
+        /*
         public async Task<Response> GetLottoNumber(Request request)
         {
             Response parseData = new();
@@ -27,19 +30,106 @@ namespace economy.Models.Lotto
 
                 var response = await _dhlotteryCoKR.httpClient.GetAsync(uriBuilder.Uri);
 
-                if (response.IsSuccessStatusCode)
+                // 요청 실패면 바로 예외 발생 -> 아래 파싱 로직으로 진행하지 않음
+                response.EnsureSuccessStatusCode();
+
+                var bytes = await response.Content.ReadAsByteArrayAsync();
+
+                // 가능한 경우 서버가 반환한 charset 사용, 없으면 euc-kr를 기본으로 시도
+                string? charset = response.Content.Headers.ContentType?.CharSet;
+                Encoding encoding;
+                try
+                {
+                    encoding = !string.IsNullOrWhiteSpace(charset) ? Encoding.GetEncoding(charset) : Encoding.GetEncoding("euc-kr");
+                }
+                catch
+                {
+                    // 지원하지 않는 인코딩이면 UTF8로 폴백
+                    encoding = Encoding.UTF8;
+                }
+
+                var content = encoding.GetString(bytes);
+
+                // 응답이 HTML(예: 에러 페이지)로 왔는지 간단히 검사
+                var firstNonWhitespace = content?.TrimStart().FirstOrDefault();
+                if (firstNonWhitespace == '<')
+                {
+                    Console.WriteLine("API 응답이 JSON이 아닌 HTML로 반환되었습니다. 원본 응답(일부):");
+                    Console.WriteLine(content.Length > 2000 ? content[..2000] : content);
+                    return new Response();
+                }
+
+                try
                 {
-                    var bytes = await response.Content.ReadAsByteArrayAsync();
-                    var jsonString = Encoding.GetEncoding("euc-kr").GetString(bytes);
-                    parseData = JsonSerializer.Deserialize<Response>(jsonString);
-                    
-                    if (parseData is null)
-                    {
-                        return new Response();
-                    }
+                    parseData = JsonSerializer.Deserialize<Response>(content) ?? new Response();
                 }
+                catch (JsonException je)
+                {
+                    // JSON 파싱 에러 시 원본 응답을 로그에 남기고 안전하게 빈 결과 반환
+                    Console.WriteLine("JSON 파싱 실패. 응답 내용(일부):");
+                    Console.WriteLine(content.Length > 2000 ? content[..2000] : content);
+                    Console.WriteLine($"파싱 예외: {je.Message}");
+                    return new Response();
+                }
+            }
+            catch (HttpRequestException e)
+            {
+                Console.WriteLine($"Request error: {e.Message}");
+            }
+
+            return parseData;
+        }
+        */
 
+        public async Task<Response> GetLottoNumber(Request request)
+        {
+            Response parseData = new();
+
+            try
+            {
+                var uriBuilder = new UriBuilder(_dhlotteryCoKR.APIUrl)
+                {
+                    Path = "/lt645/selectPstLt645Info.do",
+                    Query = $"srchStrLtEpsd={request.Number}&srchEndLtEpsd={request.Number}"
+                };
+
+                var response = await _dhlotteryCoKR.httpClient.GetAsync(uriBuilder.Uri);
+
+                // 요청 실패면 바로 예외 발생 -> 아래 파싱 로직으로 진행하지 않음
                 response.EnsureSuccessStatusCode();
+
+                var bytes = await response.Content.ReadAsByteArrayAsync();
+
+                // 가능한 경우 서버가 반환한 charset 사용, 없으면 euc-kr를 기본으로 시도
+                string? charset = response.Content.Headers.ContentType?.CharSet;
+                Encoding encoding;
+                try
+                {
+                    encoding = !string.IsNullOrWhiteSpace(charset) ? Encoding.GetEncoding(charset) : Encoding.GetEncoding("euc-kr");
+                } catch {
+                    encoding = Encoding.UTF8; // 지원하지 않는 인코딩이면 UTF8로 폴백
+                }
+
+                var content = encoding.GetString(bytes);
+
+                var jsonOptions = new JsonSerializerOptions
+                {
+                    PropertyNameCaseInsensitive = true,
+                    NumberHandling = JsonNumberHandling.AllowReadingFromString
+                };
+
+                try
+                {
+                    parseData = JsonSerializer.Deserialize<Response>(content, jsonOptions) ?? new Response();
+                }
+                catch (JsonException je)
+                {
+                    // JSON 파싱 에러 시 원본 응답을 로그에 남기고 안전하게 빈 결과 반환
+                    Console.WriteLine("JSON 파싱 실패. 응답 내용(일부):");
+                    Console.WriteLine(content.Length > 2000 ? content[..2000] : content);
+                    Console.WriteLine($"파싱 예외: {je.Message}");
+                    return new Response();
+                }
             }
             catch (HttpRequestException e)
             {

+ 122 - 0
Models/Response/Lotto.cs

@@ -2,6 +2,7 @@
 
 namespace economy.Models.Lotto
 {
+    /*
     public class Response
     {
         // 요청 결과
@@ -60,4 +61,125 @@ namespace economy.Models.Lotto
         [JsonPropertyName("bnusNo")]
         public int BonusNumber { get; set; }
     }
+    */
+
+    public sealed class Response
+    {
+        [JsonPropertyName("resultCode")]
+        public string? ResultCode { get; set; }
+
+        [JsonPropertyName("resultMessage")]
+        public string? ResultMessage { get; set; }
+
+        [JsonPropertyName("data")]
+        public LottoData? Data { get; set; }
+    }
+
+    public sealed class LottoData
+    {
+        [JsonPropertyName("list")]
+        public List<LottoRound>? List { get; set; }
+    }
+
+    public sealed class LottoRound
+    {
+        [JsonPropertyName("winType0")] 
+        public int WinType0 { get; set; } // 1등 이월 여부
+
+        [JsonPropertyName("winType1")] 
+        public int WinType1 { get; set; } // 자동 선택 당첨자 수
+
+        [JsonPropertyName("winType2")] 
+        public int WinType2 { get; set; } // 수동 선택 당첨자 수
+
+        [JsonPropertyName("winType3")]
+        public int WinType3 { get; set; } // 반자동 선택 당첨자 수
+
+        [JsonPropertyName("gmSqNo")] 
+        public int GmSqNo { get; set; } // 게임 일련번호
+
+        [JsonPropertyName("ltEpsd")] 
+        public int LtEpsd { get; set; } // 로또 회차 번호
+
+        [JsonPropertyName("tm1WnNo")] 
+        public int Tm1WnNo { get; set; } // 당첨번호 1
+
+        [JsonPropertyName("tm2WnNo")] 
+        public int Tm2WnNo { get; set; } // 당첨번호 2
+
+        [JsonPropertyName("tm3WnNo")] 
+        public int Tm3WnNo { get; set; } // 당첨번호 3
+
+        [JsonPropertyName("tm4WnNo")] 
+        public int Tm4WnNo { get; set; } // 당첨번호 4
+
+        [JsonPropertyName("tm5WnNo")] 
+        public int Tm5WnNo { get; set; } // 당첨번호 5
+
+        [JsonPropertyName("tm6WnNo")] 
+        public int Tm6WnNo { get; set; } // 당첨번호 6
+
+        [JsonPropertyName("bnsWnNo")] 
+        public int BnsWnNo { get; set; } // 당첨번호 보너스
+
+        [JsonPropertyName("ltRflYmd")] 
+        public string? LtRflYmd { get; set; } // 추첨일자
+
+        [JsonPropertyName("rnk1WnNope")] 
+        public int Rnk1WnNope { get; set; } // 1등 당첨자 수
+
+        [JsonPropertyName("rnk1WnAmt")] 
+        public long Rnk1WnAmt { get; set; } // 1등 1인당 당첨금
+
+        [JsonPropertyName("rnk1SumWnAmt")] 
+        public long Rnk1SumWnAmt { get; set; } // 1등 전체 지급액
+
+        [JsonPropertyName("rnk2WnNope")] 
+        public int Rnk2WnNope { get; set; } // 2등 당첨자 수
+
+        [JsonPropertyName("rnk2WnAmt")] 
+        public long Rnk2WnAmt { get; set; } // 2등 1인당 당첨금
+
+        [JsonPropertyName("rnk2SumWnAmt")] 
+        public long Rnk2SumWnAmt { get; set; } // 2등 전체 지급액
+
+        [JsonPropertyName("rnk3WnNope")] 
+        public int Rnk3WnNope { get; set; } // 3등 당첨자 수
+
+        [JsonPropertyName("rnk3WnAmt")] 
+        public long Rnk3WnAmt { get; set; } // 3등 1인당 당첨금
+
+        [JsonPropertyName("rnk3SumWnAmt")] 
+        public long Rnk3SumWnAmt { get; set; } // 3등 전체 지급액
+
+        [JsonPropertyName("rnk4WnNope")] 
+        public int Rnk4WnNope { get; set; } // 4등 당첨자 수
+
+        [JsonPropertyName("rnk4WnAmt")] 
+        public long Rnk4WnAmt { get; set; } // 4등 1인당 당첨금
+
+        [JsonPropertyName("rnk4SumWnAmt")] 
+        public long Rnk4SumWnAmt { get; set; } // 4등 전체 지급액
+
+        [JsonPropertyName("rnk5WnNope")] 
+        public int Rnk5WnNope { get; set; } // 5등 당첨자 수
+
+        [JsonPropertyName("rnk5WnAmt")] 
+        public long Rnk5WnAmt { get; set; } // 5등 1인당 당첨금
+
+        [JsonPropertyName("rnk5SumWnAmt")] 
+        public long Rnk5SumWnAmt { get; set; } // 5등 전체 지급액
+
+        [JsonPropertyName("sumWnNope")] 
+        public int SumWnNope { get; set; } // 전체 당첨자 수 합계
+
+        [JsonPropertyName("rlvtEpsdSumNtslAmt")] 
+        public long RlvtEpsdSumNtslAmt { get; set; } // 해당 회사 실제 판매금액
+
+        [JsonPropertyName("wholEpsdSumNtslAmt")] 
+        public long WholEpsdSumNtslAmt { get; set; } // 누적 또는 전체 판매금액
+
+        [JsonPropertyName("excelRnk")] 
+        public string? ExcelRnk { get; set; }
+    }
 }

+ 80 - 20
Views/Lotto/Index.cshtml

@@ -41,10 +41,13 @@
 
     <br/>
     <div class="table-responsive">
-        <table id="lotto" class="table table-bordered table-nowrap">
-            <caption class="caption-top">
+        @foreach (var row in result.Data.List)
+        {
+            int i = 1;
+            <table class="table table-bordered table-nowrap lotto">
+                <caption class="caption-top">
                 <h5>@ViewBag.Last 회 당첨번호</h5>
-                (@result.DrawDate 추첨)
+                (@row.LtRflYmd 추첨)
             </caption>
             <thead>
                 <tr class="text-center">
@@ -54,35 +57,92 @@
             </thead>
             <tbody>
                 <tr class="text-center">
-                    <td>@result.DrawnNumber1</td>
-                    <td>@result.DrawnNumber2</td>
-                    <td>@result.DrawnNumber3</td>
-                    <td>@result.DrawnNumber4</td>
-                    <td>@result.DrawnNumber5</td>
-                    <td>@result.DrawnNumber6</td>
+                    <td>@row.Tm1WnNo</td>
+                    <td>@row.Tm2WnNo</td>
+                    <td>@row.Tm3WnNo</td>
+                    <td>@row.Tm4WnNo</td>
+                    <td>@row.Tm5WnNo</td>
+                    <td>@row.Tm6WnNo</td>
                     <td>+</td>
-                    <td>@result.BonusNumber</td>
+                    <td>@row.BnsWnNo</td>
                 </tr>
             </tbody>
             <tfoot>
                 <tr>
-                    <th colspan="4" class="text-center">1등 총 당첨금액</th>
-                    <td colspan="4" class="text-end">@result.FirstAccumulatedAmount.ToString("N0") 원</td>
+                    <th colspan="7">자동 선택 당첨자 수</th>
+                    <td class="text-end">@row.WinType1</td>
                 </tr>
                 <tr>
-                    <th colspan="4" class="text-center">1 게임당 당첨금액</th>
-                    <td colspan="4" class="text-end">@result.FirstWinAmount.ToString("N0") 원</td>
+                    <th colspan="7">수동 선택 당첨자 수</th>
+                    <td class="text-end">@row.WinType2</td>
                 </tr>
                 <tr>
-                    <th colspan="4" class="text-center">당첨 인원</th>
-                    <td colspan="4" class="text-end">@result.FirstPrizeWinnerCount 명</td>
-                </tr>
-                <tr>
-                    <th colspan="4" class="text-center">총 판매금액</th>
-                    <td colspan="4" class="text-end">@result.TotalSellAmount.ToString("N0") 원</td>
+                    <th colspan="7">반자동 선택 당첨자 수</th>
+                    <td class="text-end">@row.WinType3</td>
                 </tr>
             </tfoot>
         </table>
+
+        var ranks = new[]
+        {
+            new { Rank = 1, Nope = row.Rnk1WnNope, Amt = row.Rnk1WnAmt, Sum = row.Rnk1SumWnAmt },
+            new { Rank = 2, Nope = row.Rnk2WnNope, Amt = row.Rnk2WnAmt, Sum = row.Rnk2SumWnAmt },
+            new { Rank = 3, Nope = row.Rnk3WnNope, Amt = row.Rnk3WnAmt, Sum = row.Rnk3SumWnAmt },
+            new { Rank = 4, Nope = row.Rnk4WnNope, Amt = row.Rnk4WnAmt, Sum = row.Rnk4SumWnAmt },
+            new { Rank = 5, Nope = row.Rnk5WnNope, Amt = row.Rnk5WnAmt, Sum = row.Rnk5SumWnAmt },
+            };
+
+        <div class="card shadow-sm border-1">
+            <div class="card-body p-0">
+
+                <!-- 데스크탑/태블릿: 헤더(표 느낌) -->
+                <div class="d-none d-md-block px-3 py-2 border-bottom bg-light">
+                    <div class="row g-2 fw-semibold text-muted small">
+                        <div class="col-2">등수</div>
+                        <div class="col-3 text-end">당첨자 수</div>
+                        <div class="col-3 text-end">당첨금</div>
+                        <div class="col-4 text-end">전체 지급액</div>
+                    </div>
+                </div>
+
+                <div class="list-group list-group-flush">
+                    @foreach (var r in ranks)
+                    {
+                        <div class="list-group-item px-3 py-3">
+                            <div class="row g-2 align-items-center">
+
+                                <!-- 등수 -->
+                                <div class="col-12 col-md-2">
+                                    <span class="badge text-bg-primary rounded-pill">@r.Rank 등</span>
+                                </div>
+
+                                <!-- 모바일: 라벨 표시 / 데스크탑: 숨김 -->
+                                <div class="col-12 col-md-3 text-md-end">
+                                    <div class="d-md-none text-muted small">당첨자 수</div>
+                                    <div class="fw-semibold">@string.Format("{0:N0}", r.Nope) 명</div>
+                                </div>
+
+                                <div class="col-12 col-md-3 text-md-end">
+                                    <div class="d-md-none text-muted small">당첨금</div>
+                                    <div class="fw-semibold">@string.Format("{0:N0}", r.Amt) 원</div>
+                                </div>
+
+                                <div class="col-12 col-md-4 text-md-end">
+                                    <div class="d-md-none text-muted small">전체 지급액</div>
+                                    <div class="fw-semibold">@string.Format("{0:N0}", r.Sum) 원</div>
+                                </div>
+
+                            </div>
+                        </div>
+                    }
+                </div>
+
+            </div>
+        </div>
+        }
+
+        <br/>
+
         당첨금 지급기한 : 지급개시일로부터 1년 (휴일인 경우 익영업일)
     </div>
 

+ 1 - 1
Views/SCSS/style.scss

@@ -142,7 +142,7 @@ footer {
     }
 }
  
-#lotto {
+.lotto {
     thead, tfoot {
         th {
             text-align: center;

+ 1 - 1
wwwroot/css/style.css

@@ -93,7 +93,7 @@ footer small {
   vertical-align: middle;
 }
 
-#lotto thead th, #lotto tfoot th {
+.lotto thead th, .lotto tfoot th {
   text-align: center;
   background-color: #eee;
   vertical-align: middle;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
wwwroot/css/style.min.css


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác