-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathget_ly_committees.R
270 lines (245 loc) · 9.45 KB
/
get_ly_committees.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#' @encoding UTF-8
#' @title Fetch Legislative Yuan Committee Meetings 取得立法院委員會會議資料
#'
#' @description
#' Retrieves and processes committee meeting information from the Legislative Yuan API.
#' This function allows you to fetch detailed information about committee meetings
#' including attendance, bills discussed, and meeting details.
#'
#' @param committee_id integer. Required. The ID of the committee. Available values:
#' \itemize{
#' \item 15: 內政委員會 (Interior Committee)
#' \item 16: 外交及僑務委員會 (Foreign and Overseas Chinese Affairs Committee)
#' \item 17: 科技及資訊委員會 (Science and Technology Committee)
#' \item 18: 國防委員會 (Defense Committee)
#' \item 19: 經濟委員會 (Economics Committee)
#' \item 20: 財政委員會 (Finance Committee)
#' \item 21: 預算及決算委員會 (Budget Committee)
#' \item 22: 教育及文化委員會 (Education and Culture Committee)
#' \item 23: 交通委員會 (Transportation Committee)
#' \item 24: 司法委員會 (Judiciary Committee)
#' \item 25: 法制委員會 (Legal Affairs Committee)
#' \item 26: 社會福利及衛生環境委員會 (Social Welfare and Environmental Hygiene Committee)
#' \item 27: 程序委員會 (Procedure Committee)
#' \item 28: 紀律委員會 (Discipline Committee)
#' \item 29: 修憲委員會 (Constitutional Amendment Committee)
#' \item 30: 經費稽核委員會 (Expenditure Review Committee)
#' \item 35: 外交及國防委員會 (Foreign Affairs and Defense Committee)
#' \item 36: 司法及法制委員會 (Judiciary and Legal Affairs Committee)
#' }
#' @param page integer. Page number for pagination (default: 1)
#' @param per_page integer. Number of items per page (default: 20)
#' @param term integer. Legislative term number
#' @param session integer. Session number
#' @param meeting_code string. Meeting code
#' @param meeting_type string. Type of meeting
#' @param attending_member string. Name of attending member
#' @param date string. Meeting date in YYYY-MM-DD format
#' @param meeting_number string. Meeting number
#' @param bill_id string. Bill ID
#' @param show_progress logical. Whether to display progress bar (default: TRUE)
#'
#' @return A list containing two elements:
#' \itemize{
#' \item metadata: List containing pagination information and request status
#' \item data: Data frame containing meeting information with columns including
#' meeting date, type, attending members, and discussed bills
#' }
#'
#' @examples
#' \dontrun{
#' # Fetch meetings from the Interior Committee
#' meetings <- fetch_ly_meetings(committee_id = 15)
#'
#' # Fetch meetings with specific filters
#' meetings <- fetch_ly_meetings(
#' committee_id = 16,
#' term = 10,
#' session = 1,
#' date = "2024-01-01"
#' )
#' }
#'
#' @importFrom httr GET content status_code
#' @importFrom jsonlite fromJSON
#' @importFrom dplyr bind_rows
#' @importFrom utils txtProgressBar setTxtProgressBar
#' @encoding UTF-8
#' @export
get_ly_committee_meets <- function(
committee_id,
page = 1,
per_page = 20,
term = NULL,
session = NULL,
meeting_code = NULL,
meeting_type = NULL,
attending_member = NULL,
date = NULL,
meeting_number = NULL,
bill_id = NULL,
show_progress = TRUE
) {
# Input validation
if (missing(committee_id)) stop("committee_id is required")
if (!is.numeric(committee_id)) stop("committee_id must be numeric")
# Initialize progress
if(show_progress) {
cat(sprintf("\nFetching meetings data for committee ID %d...\n", committee_id))
pb <- txtProgressBar(min = 0, max = 100, style = 3)
setTxtProgressBar(pb, 20)
}
# API request
base_url <- sprintf("https://v2.ly.govapi.tw/committees/%d/meets", committee_id)
query_params <- list(
page = page,
per_page = per_page,
屆 = term,
會期 = session,
會議代碼 = meeting_code,
會議種類 = meeting_type,
"會議資料.出席委員" = attending_member,
日期 = date,
"會議資料.會議編號" = meeting_number,
"議事網資料.關係文書.議案.議案編號" = bill_id
)
query_params <- query_params[!sapply(query_params, is.null)]
# Update progress - API call
if(show_progress) {
setTxtProgressBar(pb, 40)
}
# Make API request with error handling
response <- tryCatch({
httr::GET(base_url, query = query_params, httr::timeout(60))
}, error = function(e) {
if(show_progress) close(pb)
stop(sprintf("API request failed: %s", e$message))
})
if (httr::status_code(response) != 200) {
if(show_progress) close(pb)
stop(sprintf("API request failed with status code: %d", httr::status_code(response)))
}
# Update progress - parsing
if(show_progress) {
setTxtProgressBar(pb, 60)
}
content <- httr::content(response, "text", encoding = "UTF-8")
data <- jsonlite::fromJSON(content, simplifyVector = FALSE)
# Process meetings
if (length(data$meets) > 0) {
# Update progress - data processing
if(show_progress) {
setTxtProgressBar(pb, 80)
}
meetings_list <- lapply(data$meets, function(meet) {
# Extract and process meeting participants
legislators <- character(0)
# From 發言紀錄
if (!is.null(meet$發言紀錄)) {
legislators <- c(legislators, unique(unlist(
lapply(meet$發言紀錄, function(x) x$legislatorNameList)
)))
}
# From 議事錄
if (!is.null(meet$議事錄) && !is.null(meet$議事錄$出席委員)) {
legislators <- c(legislators, meet$議事錄$出席委員)
}
legislators <- unique(legislators[!is.na(legislators)])
attending_str <- if(length(legislators) > 0) paste(legislators, collapse = ", ") else NA_character_
# Extract meeting content
content <- NA_character_
if (!is.null(meet$發言紀錄) && length(meet$發言紀錄) > 0 && !is.null(meet$發言紀錄[[1]]$meetingContent)) {
content <- meet$發言紀錄[[1]]$meetingContent
} else if (!is.null(meet$會議資料) && length(meet$會議資料) > 0 && !is.null(meet$會議資料[[1]]$會議事由)) {
content <- meet$會議資料[[1]]$會議事由
}
# Create data frame row
data.frame(
會議名稱 = if (!is.null(meet$name)) meet$name else NA_character_,
會議代碼 = if (!is.null(meet$會議代碼)) meet$會議代碼 else NA_character_,
會議種類 = if (!is.null(meet$會議種類)) meet$會議種類 else NA_character_,
屆期 = as.integer(if (!is.null(meet$屆)) meet$屆 else NA),
會期 = as.integer(if (!is.null(meet$會期)) meet$會期 else NA),
會次 = as.integer(if (!is.null(meet$會次)) meet$會次 else NA),
地點 = if (!is.null(meet$會議資料) && length(meet$會議資料) > 0)
meet$會議資料[[1]]$會議地點 else NA_character_,
召委 = if (!is.null(meet$會議資料) && length(meet$會議資料) > 0)
meet$會議資料[[1]]$委員會召集委員 else NA_character_,
出席委員 = attending_str,
會議日期 = if (length(meet$日期) > 0) paste(meet$日期, collapse = ", ") else NA_character_,
會議內容 = content,
stringsAsFactors = FALSE
)
})
meetings_df <- dplyr::bind_rows(meetings_list)
} else {
meetings_df <- data.frame(
會議名稱 = character(),
會議代碼 = character(),
會議種類 = character(),
屆期 = integer(),
會期 = integer(),
會次 = integer(),
地點 = character(),
召委 = character(),
出席委員 = character(),
會議日期 = character(),
會議內容 = character(),
stringsAsFactors = FALSE
)
}
# Process metadata
metadata <- list(
total = data$total,
total_page = data$total_page,
current_page = data$page,
per_page = data$limit,
filters = data$filter,
timestamp = Sys.time()
)
# Update progress - complete
if(show_progress) {
setTxtProgressBar(pb, 100)
close(pb)
# Print summary
cat("\n\n")
cat("====== Retrieved Information ======\n")
cat("-----------------------------------\n")
cat(sprintf("Total Meetings: %d\n", metadata$total))
cat(sprintf("Page: %d of %d\n", metadata$current_page, metadata$total_page))
cat(sprintf("Records per page: %d\n", metadata$per_page))
if(nrow(meetings_df) > 0) {
# Add meeting type distribution
type_counts <- table(meetings_df$會議種類)
cat("\nMeeting Type Distribution:\n")
for(type_name in names(type_counts)) {
if(!is.na(type_name)) {
cat(sprintf(" %s: %d\n", type_name, type_counts[type_name]))
}
}
# Add session distribution
if(any(!is.na(meetings_df$會期))) {
session_counts <- table(meetings_df$會期)
cat("\nSession Distribution:\n")
for(session in sort(as.numeric(names(session_counts)))) {
cat(sprintf(" Session %d: %d\n", session, session_counts[as.character(session)]))
}
}
# Add location distribution if available
if(any(!is.na(meetings_df$地點))) {
location_counts <- table(meetings_df$地點)
cat("\nLocation Distribution:\n")
for(location in names(location_counts)) {
if(!is.na(location)) {
cat(sprintf(" %s: %d\n", location, location_counts[location]))
}
}
}
}
cat("===================================\n")
}
return(list(
metadata = metadata,
meetings = meetings_df
))
}