この記事はQiita クソアプリ Advent Calendar 2023 シリーズ2 19日目の記事です。
初めに
フルリモートで働いているエンジニアの皆さんは、ほとんどが家で働いていることが多くて、
外に出ないことがあるのではないでしょうか?
自分も例に漏れずに、ずっとデスクの前にいて、全く歩かない日があります。
これではダメだ、外に出ないと、!
だけど外に出なくても叱ってくれる人もいない、外に出ない日は罵倒されたい、いや、罵倒してほしい
だけど時々褒めて欲しい
ということで、
その日に歩いた歩数をもとに罵倒してくれつつ(時々褒める)明日の運勢を占ってくれるアプリを作りました
デモ
15歩しか歩いていないので、圧倒的な悪口、、!ありがとうございます。
ちなみにたくさん歩くと、こんなふうに褒めてくれます。
中身
中身は単純で、HealthKitで当日の歩数を取得して、それをもとにOpen AIのAPIを叩いています。
final class HealthKitUseCaseImpl: HealthKitUseCase {
~~~省略~~~
func fetchTodayStepCount(completion: @escaping (Result<Int, Error>) -> Void) {
// 当日の今までの歩数を取得する
let distanceType = HKObjectType.quantityType(forIdentifier: .stepCount)!
let now = Date()
let startOfDay = Calendar.current.startOfDay(for: now)
let predicate = HKQuery.predicateForSamples(withStart: startOfDay, end: now, options: .strictStartDate)
let query = HKStatisticsQuery(quantityType: distanceType, quantitySamplePredicate: predicate) { query, statistics, error in
guard let stepCount = statistics?.sumQuantity()?.doubleValue(for: HKUnit.count()) else { return }
if let error = error {
completion(.failure(error))
return
}
completion(.success(Int(stepCount)))
}
healthStore.execute(query)
}
}
歩数の取得
enum StepCountRange {
case veryHigh
case high
case middle
case low
case veryLow
init(stepCount: Int) {
switch stepCount {
case 0...100:
self = .veryLow
case 101...1000:
self = .low
case 1001...3000:
self = .middle
case 3001...6000:
self = .high
default:
self = .veryHigh
}
}
var prompt: String {
switch self {
case .veryHigh:
return "あなたの運命は大吉ですから始めて、最高にすごいので、人生最大級くらいの褒め言葉を送ってください。実際の名言を教えて欲しい。今日1日を幸せに終わりたい"
case .high:
return "あなたの運命は中吉ですから始めて、少し良いので、ちょっとだけ褒めてください。最後に人生の格言みたいなことを言ってください"
case .middle:
return "あなたの運命は小吉ですから始めて、まあまあなので、適当に人生の格言っぽいことを言ってください"
case .low:
return "あなたの運命は凶ですから始めて、あんまり良くないので、ちょっと罵倒してください。あと適当に人生の格言っぽいことを言ってください"
case .veryLow:
return "あなたの運命は大凶ですから始めて、話にならないくらい罵倒してパワハラ上司並みに詰めてください。"
}
}
}
取得した歩数をもとにレンジを設けて、それをもとにプロンプトを作成してます。
final class ChatGPTRepositoryImpl: ChatGPTRepository {
~~~省略~~~
func fetchTalkStreaming(chatQuery: ChatQuery) -> AsyncThrowingStream<ChatStreamResult, Error> {
openAI.chatsStream(query: chatQuery)
}
}
徐々に表示された方が体験として良いので、Streamで流しています。
OpenAIのAPIは最初は自作してましたが、便利なライブラリがあることに気がついて乗り換えました。
終わり
もはやどこに占い要素があるのか?という感じですが、これで健康的な生活が送れそうです。
開発を経て、悪口のボキャブラリーも増やすことができました。
参考
全体のコード
OpenAIのドキュメント
HealthKit
終わり!