Files
email-tracker/external/duckdb/tools/swift/duckdb-swift/DuckDBPlayground.playground/Sources/SurveyLoader.swift
2025-10-24 19:21:19 -05:00

66 lines
2.2 KiB
Swift

import Foundation
import PlaygroundSupport
import System
public enum SurveyLoader {
enum Failure {
case unableToDownloadSurveyContent
}
private static let localDataURL = playgroundSharedDataDirectory
.appending(component: "org.duckdb", directoryHint: .isDirectory)
.appending(component: "surveys")
public static func downloadSurveyCSV(forYear year: Int) async throws -> URL {
try await downloadSurveyIfNeeded(forYear: year)
return localSurveyDataURL(forYear: year)
.appending(component: "survey_results_public.csv")
}
public static func downloadSurveySchemaCSV(forYear year: Int) async throws -> URL {
try await downloadSurveyIfNeeded(forYear: year)
return localSurveyDataURL(forYear: year)
.appending(component: "survey_results_schema.csv")
}
public static func downloadSurveyIfNeeded(forYear year: Int) async throws {
let surveyDataURL = localSurveyDataURL(forYear: year)
if FileManager.default.fileExists(atPath: surveyDataURL.path) {
// survey already exists. skipping.
return
}
let surveyURL = remoteSurveyDataZipURL(forYear: year)
let (zipFileURL, _) = try await URLSession.shared.download(from: surveyURL)
try FileManager.default.createDirectory(
at: surveyDataURL, withIntermediateDirectories: true)
try Shell.execute("unzip '\(zipFileURL.path)' -d '\(surveyDataURL.path)'")
}
private static func localSurveyDataURL(forYear year: Int) -> URL {
localDataURL.appending(component: "\(year)")
}
private static func remoteSurveyDataZipURL(forYear year: Int) -> URL {
URL(string: "https://info.stackoverflowsolutions.com/rs/719-EMH-566/images/stack-overflow-developer-survey-\(year).zip")!
}
}
fileprivate enum Shell {
@discardableResult
static func execute(_ command: String) throws -> String {
let process = Process()
let pipe = Pipe()
process.executableURL = URL(fileURLWithPath: "/bin/zsh")
process.arguments = ["-c", command]
process.standardOutput = pipe
process.standardError = pipe
try process.run()
process.waitUntilExit()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
return String(data: data, encoding: .utf8)!
}
}