Skip to content

Commit

Permalink
Merge pull request #108 from TOVBUS/KAN-324
Browse files Browse the repository at this point in the history
AzureInbody Model, ViewModel 추가 및 동영상 url 추가
  • Loading branch information
uk10105 authored Aug 8, 2024
2 parents 9660675 + e8c24a2 commit 01a653a
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 3 deletions.
28 changes: 28 additions & 0 deletions Frontend-iOS/FebirdApp/FebirdApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@
E208BDEE2C62952F0094CC16 /* DailyMemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E208BDED2C62952F0094CC16 /* DailyMemo.swift */; };
E208BDF02C6295660094CC16 /* MealMemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E208BDEF2C6295660094CC16 /* MealMemo.swift */; };
E20F9CF62C63DB20006A034B /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20F9CF52C63DB20006A034B /* CustomTextField.swift */; };
E20F9CFB2C640776006A034B /* AzureInbody.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20F9CFA2C640776006A034B /* AzureInbody.swift */; };
E20F9CFF2C64086F006A034B /* AzureInbodyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20F9CFE2C64086F006A034B /* AzureInbodyViewModel.swift */; };
E20F9D012C6408A0006A034B /* AzureInbodyService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20F9D002C6408A0006A034B /* AzureInbodyService.swift */; };
E246A8DE2C5EAAF600B86617 /* ExerciseChatBotView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E246A8DD2C5EAAF600B86617 /* ExerciseChatBotView.swift */; };
E246A8E02C5EC4A200B86617 /* ExerciseCountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E246A8DF2C5EC4A200B86617 /* ExerciseCountView.swift */; };
E24CF94E2C4F887100D1548E /* CustomToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24CF94D2C4F887100D1548E /* CustomToggle.swift */; };
Expand Down Expand Up @@ -300,6 +303,9 @@
E208BDED2C62952F0094CC16 /* DailyMemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyMemo.swift; sourceTree = "<group>"; };
E208BDEF2C6295660094CC16 /* MealMemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealMemo.swift; sourceTree = "<group>"; };
E20F9CF52C63DB20006A034B /* CustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextField.swift; sourceTree = "<group>"; };
E20F9CFA2C640776006A034B /* AzureInbody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AzureInbody.swift; sourceTree = "<group>"; };
E20F9CFE2C64086F006A034B /* AzureInbodyViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AzureInbodyViewModel.swift; sourceTree = "<group>"; };
E20F9D002C6408A0006A034B /* AzureInbodyService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AzureInbodyService.swift; sourceTree = "<group>"; };
E246A8DD2C5EAAF600B86617 /* ExerciseChatBotView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExerciseChatBotView.swift; sourceTree = "<group>"; };
E246A8DF2C5EC4A200B86617 /* ExerciseCountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExerciseCountView.swift; sourceTree = "<group>"; };
E24CF94D2C4F887100D1548E /* CustomToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomToggle.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -792,6 +798,8 @@
E1BB0D532C4797C9002565B2 /* Onboarding */ = {
isa = PBXGroup;
children = (
E20F9CFD2C64085C006A034B /* ViewModels */,
E20F9CF92C64075A006A034B /* Models */,
E1BB0D562C479C93002565B2 /* Views */,
);
path = Onboarding;
Expand Down Expand Up @@ -831,6 +839,23 @@
path = Models;
sourceTree = "<group>";
};
E20F9CF92C64075A006A034B /* Models */ = {
isa = PBXGroup;
children = (
E20F9CFA2C640776006A034B /* AzureInbody.swift */,
);
path = Models;
sourceTree = "<group>";
};
E20F9CFD2C64085C006A034B /* ViewModels */ = {
isa = PBXGroup;
children = (
E20F9CFE2C64086F006A034B /* AzureInbodyViewModel.swift */,
E20F9D002C6408A0006A034B /* AzureInbodyService.swift */,
);
path = ViewModels;
sourceTree = "<group>";
};
E24F5E7F2C48EBC300724DA7 /* Meal */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1059,6 +1084,7 @@
files = (
8F0F47FA2C636FA0004E3B86 /* Inbody.swift in Sources */,
E20F9CF62C63DB20006A034B /* CustomTextField.swift in Sources */,
E20F9D012C6408A0006A034B /* AzureInbodyService.swift in Sources */,
8FE8FB362C60BA2E009CFAE9 /* NetworkManager.swift in Sources */,
E2EB25792C4E48C30094EC8E /* ChatBotMainView.swift in Sources */,
8F92DF912C4D68B40071F336 /* ExerciseRoutineLogView.swift in Sources */,
Expand Down Expand Up @@ -1091,6 +1117,7 @@
8FE8FB3B2C60BDB3009CFAE9 /* AuthViewModel.swift in Sources */,
E24CF94E2C4F887100D1548E /* CustomToggle.swift in Sources */,
E15BF03C2C60BAC10033E5C3 /* TrendAnalysisView.swift in Sources */,
E20F9CFB2C640776006A034B /* AzureInbody.swift in Sources */,
8F0F47F62C636F69004E3B86 /* Member.swift in Sources */,
E12911BB2C48EDFE009A92F7 /* PhotoPicker.swift in Sources */,
8F92DF952C4D74A10071F336 /* ExerciseGraduationView.swift in Sources */,
Expand Down Expand Up @@ -1120,6 +1147,7 @@
8F92DF8B2C4D506E0071F336 /* ExerciseRestTimerView.swift in Sources */,
E26D48B92C49F18800D63FE7 /* MemoRow.swift in Sources */,
8F0F47DC2C636BF6004E3B86 /* Config.swift in Sources */,
E20F9CFF2C64086F006A034B /* AzureInbodyViewModel.swift in Sources */,
E26D48BB2C49F93900D63FE7 /* MealChatBotView.swift in Sources */,
323408FB2C61C97500FCB9B6 /* SignInWithAppleButton.swift in Sources */,
E10FD99D2C49FB4500D80139 /* InbodyInputView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ExerciseGuideViewModel: ObservableObject {
]

func loadVideo() {
guard let url = URL(string: "YOUR_VIDEO_URL_HERE") else { return }
guard let url = URL(string: "https://strfeo.blob.core.windows.net/exercise-video/466512^Overhead_Clap^Shoulders.mp4") else { return }
let player = AVPlayer(url: url)
self.player = player
player.play()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// AzureInbody.swift
// FebirdApp
//
// Created by 이유경 on 8/8/24.
//

import Foundation

struct AzureInbody: Codable {
let weight: String
let bmr: String
let bmi: String
let bodyFat: String
let inbodyDate: String
}

struct Documents: Codable {
let fields: AzureInbody
}

struct AnalyzeResult: Codable {
let documents: [Documents]
}

struct InbodyRoot: Codable {
let status: String
let analyzeResult: AnalyzeResult?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// AzureInbodyNetService.swift
// FebirdApp
//
// Created by 이유경 on 8/8/24.
//

import Foundation
import Alamofire

class AzureInbodyService: ObservableObject {
private var subscriptionKey: String = "9ac5258525594353a9852e94af9f2ab6"

// MARK: - 이미지 분석
func analyzeImage(imageData: Data, completion: @escaping (Result<String, Error>) -> Void) {
let url = "https://doc-feo.cognitiveservices.azure.com/formrecognizer/documentModels/feo-inbody-model2:analyze?api-version=2023-07-31"
let headers: HTTPHeaders = [
"Ocp-Apim-Subscription-Key": subscriptionKey,
"Content-Type": "application/octet-stream"
]

AF.upload(imageData, to: url, headers: headers)
.response { response in
debugPrint(response)

if let httpResponse = response.response,
let operationLocation = httpResponse.headers["Operation-Location"] {
completion(.success(operationLocation))
} else {
print("network af.upload 메서드에서 문제발생! analyzeImage 메서드임")
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Operation-Location header not found."])))
}
}
}
// MARK: - 이미지 분석 결과
func getAnalyzeResult(operationLocation: String, completion: @escaping (Result<InbodyRoot, Error>) -> Void) {
let headers: HTTPHeaders = [
"Ocp-Apim-Subscription-Key": subscriptionKey
]

AF.request(operationLocation, headers: headers)
.responseDecodable(of: InbodyRoot.self) { response in
debugPrint(response)

switch response.result {
case .success(let value):
completion(.success(value))
case .failure(let error):
print("network af.request 메서드에서 문제발생! getAnalyzeResult 메서드임")
if let data = response.data, let str = String(data: data, encoding: .utf8) {
print("Response data: \(str)")
}
completion(.failure(error))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// AzureInbodyViewModel.swift
// FebirdApp
//
// Created by 이유경 on 8/8/24.
//

import Foundation
import Alamofire

class AzureInbodyViewModel: ObservableObject {
@Published var result: String = ""
private let service = AzureInbodyService()

// MARK: - 이미지 분석
func analyzeImage(imageData: Data) {
service.analyzeImage(imageData: imageData) { [weak self] result in
switch result {
case .success(let operationLocation):
print("Operation Location: \(operationLocation)") // 디버깅 출력 추가
self?.pollAnalyzeResult(operationLocation: operationLocation)

case .failure(let error):
DispatchQueue.main.async {
self?.result = "Error: \(error.localizedDescription)"
print("Error: \(error.localizedDescription)") // 디버깅 출력 추가
}
}
}
}
// MARK: - 이미지 저장
private func pollAnalyzeResult(operationLocation: String) {
service.getAnalyzeResult(operationLocation: operationLocation) { [weak self] result in
switch result {
case .success(let analyzeResult):
if analyzeResult.status == "succeeded" {
DispatchQueue.main.async {
if let jsonData = try? JSONEncoder().encode(analyzeResult),
let jsonString = String(data: jsonData, encoding: .utf8) {
self?.result = jsonString
}
}
} else if analyzeResult.status == "running" {
// 분석이 완료되지 않은 경우 일정 시간 후 다시 요청
DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
self?.pollAnalyzeResult(operationLocation: operationLocation)
}
} else {
DispatchQueue.main.async {
self?.result = "Analysis status: \(analyzeResult.status)"
}
print("Analysis status: \(analyzeResult.status)")
}
case .failure(let error):
DispatchQueue.main.async {
self?.result = "Error: \(error.localizedDescription)"
}
print("Error: \(error.localizedDescription)")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import SwiftUI

struct InbodyAddView: View {
@EnvironmentObject var navigationPathFinder: NavigationPathFinder<OnboardingViewOptions>
@StateObject var azureInbodyViewModel = AzureInbodyViewModel()

@State private var showOnboardingGaugeView = true
@State private var showSkipButton = true
Expand Down Expand Up @@ -66,7 +67,6 @@ struct InbodyAddView: View {
.padding(.top, 40)

CustomButtonView(title: "건너뛰기") {
// TODO: 분석 로직 추가
navigationPathFinder.addPath(option: .inbodyInputView)
}
} else {
Expand All @@ -77,6 +77,7 @@ struct InbodyAddView: View {

CustomButtonView(title: "분석하기") {
// TODO: 분석 로직 추가
analyzeImage(image: image!)
navigationPathFinder.addPath(option: .onboardingLoadingView)
}
}
Expand All @@ -102,9 +103,13 @@ struct InbodyAddView: View {
isImageSelected = true
}
})
.navigationBarBackButtonHidden()
.navigationBarBackButtonHidden()
}
}
private func analyzeImage(image: UIImage) {
guard let imageData = image.jpegData(compressionQuality: 0.8) else { return }
azureInbodyViewModel.analyzeImage(imageData: imageData)
}
}

#Preview {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import SwiftUI

struct InbodyInputView: View {
@EnvironmentObject var navigationPathFinder: NavigationPathFinder<OnboardingViewOptions>
// @StateObject

@State var weight: String
@State var height: String
Expand Down

0 comments on commit 01a653a

Please sign in to comment.