Parte A: Identificación y Localización de Unidades de Negocio

0. Carga de librerías necesarias

# data analysis 
library(dplyr)            # grammar of data manipulation helping to resolve data manipulation difficulties 
library(Hmisc)            # useful functions for data analysis and high - level graphics
library(foreign)          # read data stored by Minitab, SPSS, Stata
library(openxlsx)         # open, read, write,and edit xlsx files 
library(tidyverse)        # collection of R packages designed for data science

# visualization 
library(ggmap)            # spatial data visualization 
library(rgeoda)           # spatial data analysis based on software GeoDa
library(ggplot2)          # Grammar of graphics. System for declarative creating graphics
library(corrplot)         # provides a visual exploratory tool on correlation matrix
library(RColorBrewer)     # offers several color palettes
library(leaflet)          # interactive maps
library(leafsync)         # create small multiples of several leaflet web maps
library(htmltools)        # tools for HTML generation and output 

# others 
library(rlang)            # collection of frameworks and APIs for programming with R
library(classInt)         # methods for choosing univariate class intervals for mapping or other graphic purposes
library(gridExtra)        # to arrange and combine plots for easy comparison
library(knitr)            # integrates computing and reporting

# Google Maps API
library(googleway)        # provides a mechanism to access various Google Maps APIs, including plotting a Google Map from R and overlaying it with shapes and markers, and retrieving data from the places, directions, roads, distances, geocoding, elevation and timezone APIs

library(tm)  # Asegúrate de cargar este paquete antes de usar 'Corpus'

1. Clave de Google Maps API

gmaps_key <- 'AIzaSyDMtkIEvUpFccyUCGxLgXO-TzTcERfzJ3o'
register_google(key = gmaps_key)

2. Parámetros iniciales de búsqueda

latitude <- 25.6667
longitude <- -100.2895
radio <- 15000 #15 km, está en metros
# Coordenadas del punto de origen, TEC: 25.66672874952432, -100.28953999983212

3. Consulta con Google Places API: Cafés en Monterrey

# Coordenadas del punto de origen, TEC: 25.66672874952432, -100.28953999983212
# Consulta con Google Places API: Cafés en Monterrey (Solo con resultados de la primera página)
search_results_1 <- google_places(search_string = 'cafe', location=c(latitude,longitude), radius=radio, key=gmaps_key)

4. Creación de base de datos

cafes <- search_results_1$results$name
business_rating <- search_results_1$results$rating
user_ratings_total <- search_results_1$results$user_ratings_total
place_id <- search_results_1$results$place_id
lat <- search_results_1$results$geometry$location$lat
lon <- search_results_1$results$geometry$location$lng

data <- data.frame(cafes, business_rating, user_ratings_total, place_id, lat, lon)

5. Top y Bottom negocios

data_top <- data %>% slice_max(business_rating, n = 10)
data_bottom <- data %>% slice_min(business_rating, n = 10)

6. Visualización en mapa interactivo

leaflet(data_top) %>% addTiles() %>%
  addCircleMarkers(~lon, ~lat, popup = ~cafes, color = "green", radius = 15)
leaflet(data_bottom) %>% addTiles() %>%
  addCircleMarkers(~lon, ~lat, popup = ~cafes, color = "red", radius = 15)

7. Análisis de Sentimiento (Sentiment Analysis)

reviews_top <- google_place_details(place_id = data_top$place_id[1], key = gmaps_key)
reviews_bot <- google_place_details(place_id = data_bottom$place_id[1], key = gmaps_key)
reviews_top
## $html_attributions
## list()
## 
## $result
## $result$address_components
##                  long_name               short_name
## 1                  Local 8                  Local 8
## 2                      951                      951
## 3     Avenida Pico Bolívar         Av. Pico Bolívar
## 4   Las Puentes 10º Sector   Las Puentes 10º Sector
## 5 San Nicolás de los Garza San Nicolás de los Garza
## 6               Nuevo León                     N.L.
## 7                   Mexico                       MX
## 8                    66460                    66460
##                                         types
## 1                                  subpremise
## 2                               street_number
## 3                                       route
## 4 sublocality_level_1, sublocality, political
## 5                         locality, political
## 6      administrative_area_level_1, political
## 7                          country, political
## 8                                 postal_code
## 
## $result$adr_address
## [1] "<span class=\"street-address\">Av. Pico Bolívar 951</span>-Local 8, <span class=\"extended-address\">Las Puentes 10º Sector</span>, <span class=\"postal-code\">66460</span> <span class=\"locality\">San Nicolás de los Garza</span>, <span class=\"region\">N.L.</span>, <span class=\"country-name\">Mexico</span>"
## 
## $result$business_status
## [1] "OPERATIONAL"
## 
## $result$curbside_pickup
## [1] TRUE
## 
## $result$current_opening_hours
## $result$current_opening_hours$open_now
## [1] TRUE
## 
## $result$current_opening_hours$periods
##   close.date close.day close.time  open.date open.day open.time
## 1 2025-05-11         0       1700 2025-05-11        0      1000
## 2 2025-05-05         1       2100 2025-05-05        1      0700
## 3 2025-05-06         2       2100 2025-05-06        2      0700
## 4 2025-05-07         3       2100 2025-05-07        3      0700
## 5 2025-05-08         4       2100 2025-05-08        4      0700
## 6 2025-05-09         5       2100 2025-05-09        5      0700
## 7 2025-05-10         6       1700 2025-05-10        6      1000
## 
## $result$current_opening_hours$weekday_text
## [1] "Monday: 7:00 AM – 9:00 PM"    "Tuesday: 7:00 AM – 9:00 PM"  
## [3] "Wednesday: 7:00 AM – 9:00 PM" "Thursday: 7:00 AM – 9:00 PM" 
## [5] "Friday: 7:00 AM – 9:00 PM"    "Saturday: 10:00 AM – 5:00 PM"
## [7] "Sunday: 10:00 AM – 5:00 PM"  
## 
## 
## $result$delivery
## [1] FALSE
## 
## $result$dine_in
## [1] TRUE
## 
## $result$formatted_address
## [1] "Av. Pico Bolívar 951-Local 8, Las Puentes 10º Sector, 66460 San Nicolás de los Garza, N.L., Mexico"
## 
## $result$geometry
## $result$geometry$location
## $result$geometry$location$lat
## [1] 25.74284
## 
## $result$geometry$location$lng
## [1] -100.2709
## 
## 
## $result$geometry$viewport
## $result$geometry$viewport$northeast
## $result$geometry$viewport$northeast$lat
## [1] 25.74422
## 
## $result$geometry$viewport$northeast$lng
## [1] -100.2695
## 
## 
## $result$geometry$viewport$southwest
## $result$geometry$viewport$southwest$lat
## [1] 25.74152
## 
## $result$geometry$viewport$southwest$lng
## [1] -100.2722
## 
## 
## 
## 
## $result$icon
## [1] "https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png"
## 
## $result$icon_background_color
## [1] "#FF9E67"
## 
## $result$icon_mask_base_uri
## [1] "https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet"
## 
## $result$name
## [1] "Amorian - Barra De Café"
## 
## $result$opening_hours
## $result$opening_hours$open_now
## [1] TRUE
## 
## $result$opening_hours$periods
##   close.day close.time open.day open.time
## 1         0       1700        0      1000
## 2         1       2100        1      0700
## 3         2       2100        2      0700
## 4         3       2100        3      0700
## 5         4       2100        4      0700
## 6         5       2100        5      0700
## 7         6       1700        6      1000
## 
## $result$opening_hours$weekday_text
## [1] "Monday: 7:00 AM – 9:00 PM"    "Tuesday: 7:00 AM – 9:00 PM"  
## [3] "Wednesday: 7:00 AM – 9:00 PM" "Thursday: 7:00 AM – 9:00 PM" 
## [5] "Friday: 7:00 AM – 9:00 PM"    "Saturday: 10:00 AM – 5:00 PM"
## [7] "Sunday: 10:00 AM – 5:00 PM"  
## 
## 
## $result$photos
##    height
## 1    3124
## 2    3512
## 3    3024
## 4    4000
## 5    4032
## 6    4080
## 7    4032
## 8    4000
## 9    3648
## 10   4032
##                                                                                             html_attributions
## 1            <a href="https://maps.google.com/maps/contrib/114821316621740777993">Amorian - Barra De Café</a>
## 2            <a href="https://maps.google.com/maps/contrib/114821316621740777993">Amorian - Barra De Café</a>
## 3                       <a href="https://maps.google.com/maps/contrib/102917186141684532040">Iván Márquez</a>
## 4     <a href="https://maps.google.com/maps/contrib/106464295202899192581">Mariana Nohemi Lumbreras Reyes</a>
## 5                      <a href="https://maps.google.com/maps/contrib/105870907151295064618">Andrea Torres</a>
## 6                     <a href="https://maps.google.com/maps/contrib/110123376132722266512">Arturo Sánchez</a>
## 7                    <a href="https://maps.google.com/maps/contrib/104175095122475628469">Matilde de leon</a>
## 8  <a href="https://maps.google.com/maps/contrib/115089920418965643685">Nadia Guadalupe De La Cruz Garcia</a>
## 9                         <a href="https://maps.google.com/maps/contrib/111040827819759648660">Ale Cortez</a>
## 10                 <a href="https://maps.google.com/maps/contrib/102829739202666023610">Krystal Marroquín</a>
##                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 photo_reference
## 1                                                                                                                                                                                                                                                                                                                               AeeoHcJyRInVy2ZZwLW36C4Dgxd7sExzclRWBuzYXLdEY_LsjNyx1S_V-n7ISSHOHNtfyJwwq-i1trxcfM0aquiDXysYRYKO5m1FWG_DpZNWcu-hPq-4hSwTyE2f4OWcd2xZVFWHdtzgr83KDaFWO-ULgidVjz-ntPMWtOLBUapFN7HW_WVc4i5sMv3USBgPrSFqo3LXgmV58hmGYhEOlN2o0j0ldrZYOpWISl4cZxvVWl48nEk06FBwRU45rUkipe9ILm75ia1Wt3xvGchT3V8-NQFBR0puwxyMgc1lgV_bW5pLBKUTz1Pj9zshP7TMrd5MIrYEU_PeLA8
## 2                                                                                                                                                                                                                                                                                                                               AeeoHcL_DP0OwAl24LGalWosbtUElMrwZ-KWVsFJXu2wbMJTBff0NI_CTZPstnVU0OWDhOmpC06Q9OZYPeBTabcLSdoldomWKB9AL74oljmHUCoD8IYBrM9m-qZWqLy_OIEtMDxNE3uDX92KdnCgifg9k8sJesqYE7khkEhEatWsPerLsqA5MWgWAmA4bRgl086jm0mDExvRHqn7j-LBw5LyFgw2b8b_vdoX3Jjy3KpacqR45PEc05BQ4akqODQOaHFvwRELmOk169vPi43DCSJ2GLAH5HhA3T52tXYwHqWmE3IV59-E9VA43MQ98kkXsrcX7cTZL1g7i8s
## 3    AeeoHcI882uNJSxnXZHEIEzG38PAtaRDt21Y7O1qZRQFPxkz9wzF4cim_qjQdp3pERO0MH7pKmN5T0rPLcgEUnl9LqA7dfJpub5GAFCXfNB2_IR51kqADfiKOwtgUWZiw0atmwIGm3BCzen-JYQ364307_x7905rbz0xI6L_3Pd4zruyc0vz_W19pnoGJISkU6BbvCTwrRpzCdqBTeaeDsvKtbjjSEzHfUo2-8PjyvwBXKX3hyzI8yoBXkSW_GgmNurx45DHJFBlv7fPoq8ajYbCw_kg_aNc40m4Aj8JOPFvWrJ5Pzk-OnjQxVsCaJmsLuu9_dh7_yTDZEdxYvMb_hLu-88LIVzpgX6DQMf0KUvgPMPCzp3CUC69n1nYsV_Ats1A-k3VNCQGXjsMJodaI43XsG7nQCkfdKDqSuvJuZJFMJlmPVkaJgJ-Wj-6oiEqQC-c6WHc-wt0zXc_QIVVgHXybcxFvuyYv-3-KzfoIW8dGxd3fzbHZZ8j3fjQkhnWN-topvF7agI18PQu8XVUx8Q5fsoM7YzobYJkLGtkVQtI2t-_sHjQZ6Hny0ayyvjoL4QfPJNsVlK5n441pLBaLHLFQMKym2nedR-tlpZiIEZZqxZBuZKePygIMHPl6ms7ArwNgPNDvg
## 4    AeeoHcIM9HLFn6_ZAYBraG3U_lJaIVzWGer_J-wYVTdKSxRLJJCVYw1zX4KIWJ-6ZTTDLC1b9-_2vQL_fHsaQoMpQpvN0Fzqa2Jz5bLCgfUKIR0klznVRSWvuvmUn4Jf2w36_K4oQFjnKJxhywWZsyiIFA3JxXeZmyMyCGaYC8M0_sa54i6MpN11dBAFAkmkLKbH4TXys0e3sXh8LyGBQcB8HcK-AqMneDAtlec3Zbih-1uy5rrwkd1W-9FYUP2QgPYi-IwlT4SMbF3cWHDFA8WpPHBgwYLmNf426nUPeLXjlHFmznxsO0x1y8k_5eEyPS3d1Oc25_qazR-MgmCpMaoGlvBAQWKLQBL8rECLGsLMeyMzcNUGW4QZqv4EZnsGQk4WDaXsoV8HVa41yNBUUpzq6Odvqp3jCpyrPwHrmUpGPWXk_CyqJrih8Q-fJiKYT1UMhS8SOCS9HpXwJFOpBnqE3349D946-Rj5TlMeblUAPhmy8bz9jWQW7N9HGy6KXUobIPl48xE99UxOOHwt_wJeaVzEVVXhyJKo1k7Bk3QgRE8W1y14kcJuQe0H6MvJIjOSyc5hksE-MCuQTEwfDh4NaQOQ9Xa4fqtmc7iwk0hYfZfU3q9mDrkAaTDiorXxrS6_pW_3vg
## 5    AeeoHcKd2rtFpXLOHyhcjumqd35Cjsb3EJ1voeG4BnX0Gn2dRYsaWppG8QomQo8JSyu_zggFW5CmIZgojtD5e27jNjWlg8GZnbbW0SZQD7liFZfNSm_DAcokTBbrEFUqf00c5n5rGU3P4GXT6LZKLlWvIXVShfpW32kEPXV0hAgi1wHDA2UwC6YPTFPFOxDdg_bc1DaKEEsUrjy8TabqCcgRKXsEoCyYRPNHwqdmfSY3GAXiDYxQllouUKWMmrDlIVQF0ESy-f7oQMJC11O3UBlIjE3JhVRNKqBIXj_rzHpGSXoWK68fFqL6feDRXLOVHyzFG_4NLzmoxp_1R15F28eBt9yO_JYKWPj2a98BchmqXod8wQ2CMAI0_YG6Wvt8Cp936qsEfZXpIDpNi9qdccTFwSRBe_VerLxFQtKEOSdLIYVve7rHWdH44AImwqgy-KvKcQWGgTvl33ET3RHsExxPBHbeCltX_4iyxtluxA6OOcLGVYH5FCMuPFwsx0pJpNUdeSVqrXqnU-BCu8_uHUPC8BTxaO_i1_VrPHwKuEpbxUgulnLX13-trzzm1rRq9LQKLwt2YPosKGTDnjKyjnsuGiOioYefmZy07A1-zUBB91_D6XKGdd4_GUXsX8JWQBpzt2Cg7w
## 6  AeeoHcIzWRpuQrV1Rcjr3FoJI_rwzhIDJD8YDrmHdgsKNDrFOswU3VKZ0SY2oNBu36Uakvt6sLVcVWoI-N9KD8SNZDkfpGEmLEG3YPzoeGXLKTiwZjDhozDUfdgXKhbxgu2l-1spp4pAOLoDGItItDCvWxUE9hEUrZHNyU1CLAtELkvIgf2Lz8pFT1ib1In5YEinsvNoQh3S2bbXX19ltz22lI3m1isHzvXt7jJsz1tkck6NKu0ZioXVcIWS0tsMLtbg90URyzzEpYCCjhXCU5KvoM9Iv2kADzX7yRGU7kh-AfHhN9y5H4FJrRy0LNUdqumelZXiAu3piGnW48BCkERaUToM8P12yiKisa1AAWwsQ9g3X_vfNARQsvZGacLO4l1O-SMpTauv5kmXAI2EssTPggIAcWBKoVmv4Q5nvBahCXXlJPSss8s1QB8pZPTe0BwxT7mK49SD4OOE4WdqtqtxzlAGLpFctu2XW4sgrWf7rSwUZNds3djM40fMMm3CDKoTcWIa308Axm7knp5XhzjP2a0E83VtTxywPaAyOCI3R-uIqoSsPSsmFQpg4GF4A0Amem41F5QCcu6aZn3fjyttxbRtO6-0J2Xh4rzeIGJC3OMrGQpk0jn5bYMFpM8lwcZVYcdmtciY
## 7  AeeoHcL5fZe19i5CKPRS-3D7157zOQm8gLzxwKxemttvVJ8UgLoL2z4hbg48cOolSVXryewelgbxA6DRlbnO5neiAyUjsFOjGjoelFWNUiZqVbG2zlAAGDZOcSRQgCR-P7ybHXAWW4AnUKJn9xen6XKPz2NzJy2aBa_yDt8P-T2N9Rz29GKB6iZ4J80Ih_ar1v_-XxIPO08csPaJfkNLEid5tv_URvGkfF8vtrQLOnsaEzff-pC8_yPYZRTA5TjeQ_hcrekGm2S1itjv-50r-i1eS6qFIQhoNCB3tNbiuiF8VnIlvMIiKwjLiIkmWodn8HRZwQdkirtWKoqwuBh9LhGCu0aIvhxgDEpCDie1eqrEfH68t1SRHp9A6w0r_C9Wk1me_UWjCOF2Etf1InYjXOnYcp_c-MOXAF75TIxe5IliazDTzhplq79zAWExYic4PlLrmytp652YcyRVXfaJpAoAjyPLgPfx5GQ_LLRrfMlp9YgEX4AIvZvciyiUQ9PxXx6Ia_3WcYkffufimgJ1VYJXvIQSAg8PrdQW_v26_RiNWt6wdbsFmQ0rHrFuz-cMcvj7vJTXFVcq_f2cSLA554-mq2wzDgTTZv-Ji0cZfK4cunE1wpvVgH9hx7lPhMdqdd629i1WuTOt
## 8    AeeoHcIvDvjpl8Y0Te-JuDz3SthHxD10rAumCKzwu1k4eTHDy9tcny72mxEbPK5jSpl91arUait7xM-3nsTGQySHI64WQLj7oejDL50O2Ah0CVltSn0mZ02EsNwuQKkl0hg7zBlvzaCNjHRdSOMJdbKbVn6j4r2mbEppxF7dqVmxlqHPZt2cV5Gk7MPBRGDrjxUwLRCm8I20Bt-6jr4mZNMKsOOzF_U3qMhUGcdBqTGNjKjtZFPLUhg0NHpVq3TNdmpI86QD_AeMyffrBmcCBLTWhXe94ygs8tZvwDrlECOOtc9FCeeUM-PkdWlghiV4pA7ypQCkiwlBGeYXVPb_Z7rGw0XKd5H0kk0Wv5CMdUWow03GmZX3EP8qeXoVNA-owPDyLI0xFm8XCk-IoyqqgFMBPUjp1187d8ub2VxkFgY1jwq4wa9T3rbGh2xSiaYKBGn1dQJYrJopCZb-gdb4XTmy2UpkU0P67rtBMiy6Hxz0kcsWfGfJf_ptX9B5Jb8EEawxvqHr2QH6dD474AKtZqqOdBWNOADDk7jh-b9PN4EeU488YFICQEZcO2stFegNbdBUoaPBlml1x-MJo9sVlyQuG7fPPaNvS1Vuq3v79tH1Qo45PXxhcEDef_30mo0Y7G8P--FVnw
## 9    AeeoHcLwbSbd2MrNGMfvU6sN5kU_mn61oIA73sVQUjyvwwBEAyTQh4k2yLOr1SzFVOrTJJbPAFEOu05lvR3wwOuRAI1FUyx33CuO108OvHS-cxfVgAnQLUWYgc4kuwAwZJaDqzAqZWqZEaQkt9TEfM3qtxt42TKRQeuC1bg20fIdZegxZmBogVsFwb1tWbWpex1EF535fEWSHl8L_KBypyNB8m_Eqqr07xUUPncF0Zlt0Zcm4TUq30dVmbnPm9PI1OkvCmDGwoNRmV_1Hl5BNu_lu-VuLMayzis1SLrgmpIrwRBowXOs78KfueaKAbrtjcZOVnKh_TJYLOqFEk68FY_eFfVAQ7-2ngECgJwSNnIjrqyEvfRqltPIjc2PFbE_PkKZ_1mMtV2NfohRAzy4N_LLeykmSkzNyXIRecQF--fHsgXKWiCwNPRHld-g3Iqq8tjKC6mUJ6emX0x40DzzHzA1WwPZeJ2fgo92efrBfTuEOEAmGgQsPly-1PWzcQMnIRwyDk6vOXLwPyfU3OPbAzqVJ_XEsxhQSTvAHTHIsl40g4mWlL1I98BfcZuj4dsegKFzkHEmDvIaoZqn-CVDIJBqUpLAxMF4igQ9A-KJannBS97PLR2PiYBPtEr4tgK5YiYT5FHqEA
## 10   AeeoHcJa0vBu52aXdoSPSJhcgx_XDJcWC71xfR7u4chnV0UOLsDm7i25t5ZXkBu8YtHyQd_ud9bcsC44cqS2ZVKENjfr9cGbtqdTktTMa7AxOwxTXlGUvvNmTMU_XVekmsaCbWGFY1uwWY4xPZk3-LBAY6T5fG8tpaegrfZ0D7GnaycEoyjXiudt7ULpiHvFHJPPsCYZ8CIlGCjv6BkSa2gGhEanhyDTnBHiCbcR3ZAqgEx6PXTE-waEikaV4t_1TA3izz6qZvnz1r7fz_SglmFg4_kz4SlGYZevZBqy9zIoLfsl4Odu3z5HdNcB4jLypYgEVXWJr3r6NOCtTr2WKtSdKEcuy0z8_8E39uhObasZZs2R7Y-doUHCdjwIm7RVwn76IpsLHy2UxwCLApRsqXe_2KPzGMOpj-P7IVPwetPAYoTnOa6u979ZxcqwZDVbCXhQz-x5Oelunn6BZCsn95zIjGRy5Wy7mxWP3mWOzqJFAAaxqdB7K-krSVuo0PaQtfBfwHEPdDHlcXEzjTE_eyY9QMy7txBO-ZKI7klt0_1-m65JnpBWxzTzHJWs3LSGVnrMKihKBNf3dERvPwExkScvHWWwcL5B8M3-YmfZEn73C27a7BNIXRh2bkZbMcN6oCPBzjBnqw
##    width
## 1   2517
## 2   3000
## 3   4032
## 4   3000
## 5   2268
## 6   3072
## 7   1816
## 8   3000
## 9   2736
## 10  3024
## 
## $result$place_id
## [1] "ChIJcftURgyVYoYRyJvUaf5muzI"
## 
## $result$plus_code
## $result$plus_code$compound_code
## [1] "PPVH+4M San Nicolás de los Garza, Nuevo Leon, Mexico"
## 
## $result$plus_code$global_code
## [1] "75QXPPVH+4M"
## 
## 
## $result$rating
## [1] 4.9
## 
## $result$reference
## [1] "ChIJcftURgyVYoYRyJvUaf5muzI"
## 
## $result$reviews
##                        author_name
## 1                   Fernando Rosas
## 2                       Ale Cortez
## 3 Miriamtenoriomoran Tenorio moran
## 4                     Ivon Márquez
## 5            Maria Gonzalez Moreno
##                                                          author_url language
## 1 https://www.google.com/maps/contrib/114218607882112803402/reviews    en-US
## 2 https://www.google.com/maps/contrib/111040827819759648660/reviews    en-US
## 3 https://www.google.com/maps/contrib/104656141222822926093/reviews       es
## 4 https://www.google.com/maps/contrib/109138756091370151392/reviews       es
## 5 https://www.google.com/maps/contrib/103637632303220566881/reviews    en-US
##   original_language
## 1                es
## 2                es
## 3                es
## 4                es
## 5                es
##                                                                                                               profile_photo_url
## 1 https://lh3.googleusercontent.com/a-/ALV-UjVWB-3TR3eAWLiJ--kmCo0wwhz-T7OOYoFwCvHFNJOp3XnPp86Z5w=s128-c0x00000000-cc-rp-mo-ba5
## 2       https://lh3.googleusercontent.com/a-/ALV-UjVuvQMOEO4D_rpfDEmep7UU67FgNgC4CoMmx24dXdYDqn0uKdSB=s128-c0x00000000-cc-rp-mo
## 3       https://lh3.googleusercontent.com/a-/ALV-UjU5SDwVAeQKAZWgHRC36bOZv-O-Duus3aZ2RNjSkcwaqgy-YVAd=s128-c0x00000000-cc-rp-mo
## 4       https://lh3.googleusercontent.com/a-/ALV-UjXMFrvUjn3Zo37WZzXTslIMh5SJOi-c15Yzq007untjgd4645Jk=s128-c0x00000000-cc-rp-mo
## 5          https://lh3.googleusercontent.com/a/ACg8ocJ2RyVd6kQwASQINMUjWFzmdZb7sAyx6DjIpVDj8o7k_SMVFg=s128-c0x00000000-cc-rp-mo
##   rating relative_time_description
## 1      4               2 weeks ago
## 2      5               a month ago
## 3      1               a month ago
## 4      5               a month ago
## 5      5               a month ago
##                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    text
## 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          The staff is excellent, always friendly and attentive. They have a wide variety of extraction methods, such as V60, AeroPress, Kalita, Origami, among others, which is ideal for specialty coffee lovers.\n\nThe only downside is that the place is quite small, making it more suitable for one or two people, depending on where they sit. Still, it is worth visiting for the quality of the coffee and the good service.
## 2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               I love this place, their coffee is delicious.\nYou also have a great variety of foods, and good music and the guys who work there are very friendly.\nA suitable place to go with someone to have a snack, and to go to work and study.
## 3 La actitud del personal puede marcar una gran diferencia en cómo los clientes perciben un lugar, sin importar qué tan bueno sea el ambiente o la calidad de los alimentos.\nQuiero compartir mi experiencia reciente en su establecimiento, ya que considero importante brindar retroalimentación constructiva. El día de nuestra visita, disfrutamos del ambiente agradable del lugar y de la calidad de los alimentos, pero desafortunadamente, el servicio que recibimos afectó nuestra experiencia de manera significativa.\n\nAl ingresar, intentamos ajustar una silla para acomodarnos mejor como familia, pero nos informaron que no era posible moverlas. A pesar de ello, respetamos las normas del lugar y nos acomodamos como se indicaba. Sin embargo, notamos una actitud grosera por parte del miembro del personal que nos atendió. Este comportamiento incluyó aventar las servilletas sobre la mesa y un tono molesto al entregar las bebidas, lo que nos hizo sentir incómodos.\n\nEntendemos que todos podemos tener días complicados, pero esperamos que nuestro comentario sea de utilidad para que puedan revisar estos aspectos y brindar una experiencia más agradable a todos los clientes.\n\nAgradecemos su atención y quedamos a disposición para cualquier aclaración. Nos encantaría regresar en el futuro y disfrutar del excelente potencial que tiene su cafetería.
## 4                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Muy agradable lugar, super cómodo para platicar o trabajar, amabilidad y excelente servicio.\nDe los platillos ni hablar, muy rico sabor, me encantan los waffles y el matcha el más delicioso 🤤\nLo que también me agrada es que tiene muy amplio estacionamiento y que jamás pega el sol de frente.
## 5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Excellent place to go for a snack.\nTheir coffee is delicious and they have a wide variety of sweet and savory foods.\nIf customer service is very good, all the guys are always attentive and friendly.\nRecommended 100%
##         time translated
## 1 1744859282       TRUE
## 2 1742366192       TRUE
## 3 1742431624      FALSE
## 4 1742504314      FALSE
## 5 1742365015       TRUE
## 
## $result$serves_breakfast
## [1] TRUE
## 
## $result$takeout
## [1] TRUE
## 
## $result$types
## [1] "cafe"              "restaurant"        "food"             
## [4] "point_of_interest" "store"             "establishment"    
## 
## $result$url
## [1] "https://maps.google.com/?cid=3655628765424557000"
## 
## $result$user_ratings_total
## [1] 96
## 
## $result$utc_offset
## [1] -360
## 
## $result$vicinity
## [1] "Avenida Pico Bolívar 951-Local 8, Las Puentes 10º Sector, San Nicolás de los Garza"
## 
## $result$website
## [1] "https://www.instagram.com/amorian.cafe/"
## 
## 
## $status
## [1] "OK"

Tops y Bottoms

# TOP 5 MEJOR VALUADOS
top5 <- data %>%
  arrange(desc(business_rating)) %>%
  slice_head(n = 5)

ggplot(top5, aes(x = reorder(cafes, business_rating), y = business_rating)) +
  geom_col(fill = "darkgreen") +
  coord_flip() +
  labs(
    title = "Top 5 Cafés Mejor Valuados",
    x = "Sucursal",
    y = "Calificación (máx. 5)"
  ) +
  ylim(0, 5) +
  theme_minimal()

# BOTTOM 5 PEOR VALUADOS
bottom5 <- data %>%
  arrange(business_rating) %>%
  slice_head(n = 5)

ggplot(bottom5, aes(x = reorder(cafes, business_rating), y = business_rating)) +
  geom_col(fill = "brown3") +
  coord_flip() +
  labs(
    title = "Top 5 Cafés Peor Valuados",
    x = "Sucursal",
    y = "Calificación (máx. 5)"
  ) +
  ylim(0, 5) +
  theme_minimal()

Parte B: Análisis de Percepción del Cliente (Sentiment Analysis)

8. Wordcloud

library(tm)
library(wordcloud)  # Cargar la librería 'wordcloud'

# Comentarios de los negocios mejor valorados
top_text <- reviews_top$result$reviews$text

top_corpus <- Corpus(VectorSource(top_text))
top_corpus <- tm_map(top_corpus, content_transformer(tolower))
top_corpus <- tm_map(top_corpus, removePunctuation)
top_corpus <- tm_map(top_corpus, removeWords, stopwords("spanish"))
wordcloud(top_corpus, max.words=100, random.order=FALSE, colors=brewer.pal(8, "Dark2"))

8.1 Wordcloud

# Comentarios de los negocios peor valorados
bot_text <- reviews_bot$result$reviews$text

top_corpus <- Corpus(VectorSource(top_text))
top_corpus <- tm_map(top_corpus, content_transformer(tolower))
top_corpus <- tm_map(top_corpus, removePunctuation)
top_corpus <- tm_map(top_corpus, removeWords, stopwords("spanish"))
wordcloud(top_corpus, max.words=100, random.order=FALSE, colors=brewer.pal(8, "Dark2"))

# Comentarios de los negocios peor valorados
bot_text <- reviews_bot$result$reviews$text

bot_corpus <- Corpus(VectorSource(bot_text))
bot_corpus <- tm_map(bot_corpus, content_transformer(tolower))
bot_corpus <- tm_map(bot_corpus, removePunctuation)

9. Análisis de Sentimiento

library(syuzhet)

# Análisis de sentimientos para los comentarios de los negocios mejor y peor valorados
top_sentiment <- get_nrc_sentiment(top_text)
bot_sentiment <- get_nrc_sentiment(bot_text)

# Visualización de emociones de los negocios mejor valorados
barplot(colSums(top_sentiment), las=2, col="blue", main="Emociones - Negocios con mejor calificación")

# Visualización de emociones de los negocios peor valorados
barplot(colSums(bot_sentiment), las=2, col="red", main="Emociones - Negocios con peor calificación")

10. Distribución del Sentiment Score

# Obtener vector de texto limpio
bot_vector <- sapply(bot_corpus, as.character)

# Sentiment score
bot_scores <- get_sentiment(bot_vector, method = "syuzhet")

# Mostrar distribución
hist(bot_scores,
     breaks = 10,
     col = "steelblue",
     main = "Distribución del Sentiment Score",
     xlab = "Sentiment Score")

11. Distribución Positivo, Negativo, Neutral

get_sentiment_summary <- function(text) {
  sentiment_scores <- get_sentiment(text, method = "syuzhet")
  summary <- table(cut(sentiment_scores, breaks=c(-Inf, -0.1, 0.1, Inf), labels=c("Negativo", "Neutral", "Positivo")))
  return(summary)
}
get_sentiment_summary(top_text)
## 
## Negativo  Neutral Positivo 
##        1        0        4
get_sentiment_summary(bot_text)
## 
## Negativo  Neutral Positivo 
##        2        0        3

Conclusiones

  • Los cafés mejor valorados tienen una calificación superior a 4.0, mientras que los peores negocios tienen calificaciones por debajo de 2.5, lo que indica una gran disparidad en las preferencias de los clientes.
  • Estos extremos en las calificaciones sugieren que el servicio y la calidad de los productos son factores clave en la percepción del cliente. Los negocios en el top 10 tienden a ser muy consistentes en la satisfacción de sus clientes.
  • Los negocios mejor valorados están distribuidos de manera más homogénea en áreas centrales de Monterrey, mientras que los negocios peor valorados suelen concentrarse en áreas periféricas o menos transitadas, lo que podría indicar una relación entre la localización y la calidad percibida por los clientes.
  • El análisis de los sentiment scores muestra que los negocios mejor valorados tienen una distribución positiva de los sentimientos, con puntuaciones que se agrupan cerca del rango positivo (+0.1 a +0.5).
  • En cambio, los negocios peor valorados tienen un sentiment score negativo, lo que indica una percepción general desfavorable, con una concentración de puntuaciones en el rango negativo (-0.1 a -0.5).
  • Los negocios con menor puntuación podrían mejorar en áreas críticas como el servicio al cliente, la calidad del producto y la atención en general.
  • Los comentarios negativos sobre la temperatura de las bebidas, tiempo de espera y actitud del personal sugieren que la eficiencia y la calidad del servicio son áreas clave para mejorar.
  • Los negocios mejor valorados tienden a tener un número significativamente mayor de reseñas que los peor valorados. Esto podría indicar que la reputación positiva de estos negocios atrae a más clientes dispuestos a dejar su reseña.
  • Los negocios mejor valorados suelen tener una mayor consistencia en las reseñas positivas, mientras que los negocios peor valorados presentan una gran variabilidad en las opiniones, lo que podría indicar que la calidad del servicio es inconsistente.
  • Para los negocios peor valorados, una intervención centrada en mejorar el servicio al cliente y la calidad del producto podría elevar significativamente la percepción de los clientes.
  • Evaluar la accesibilidad y ubicación de los negocios peor valorados podría ser relevante, dado que algunos podrían estar en zonas con menor afluencia de clientes.
LS0tCnRpdGxlOiAiQWN0aXZpZGFkIEdvb2dsZSBNYXBzIFJldmlld3MiCnN1YnRpdGxlOiAiQWN0aXZpZGFkIDMuMSAgfCBQbGFuZWFjacOzbiBFc3RyYXTDqWdpY2EgQmFzYWRhIGVuIEFuYWzDrXRpY2EgUHJlc2NyaXB0aXZhIgphdXRob3I6IAogIC0gSMOpY3RvciBHdWFkYWx1cGUgZGUgbGEgR2FyemEgVHJldmnDsW8gKEEwMTE3Nzk2MCkKICAtIE1hcmlhbmEgTGVhbCAoQTAxNTcwOTc3KQogIC0gRmVybmFuZGEgU2FuY2hleiBHdXRpZXJyZXogKEEwMTYxMzM2MCkKICAtIEplbmFybyBNYXJ0w61uZXogKEEwMTcyMTk1MSkKZGF0ZTogIk1heW8gMjAyNSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICBjc3M6IHN0eWxlcy5jc3MKLS0tCgojICpQYXJ0ZSBBOiBJZGVudGlmaWNhY2nDs24geSBMb2NhbGl6YWNpw7NuIGRlIFVuaWRhZGVzIGRlIE5lZ29jaW8qCgojIyAqMC4gQ2FyZ2EgZGUgbGlicmVyw61hcyBuZWNlc2FyaWFzKgoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBkYXRhIGFuYWx5c2lzIApsaWJyYXJ5KGRwbHlyKSAgICAgICAgICAgICMgZ3JhbW1hciBvZiBkYXRhIG1hbmlwdWxhdGlvbiBoZWxwaW5nIHRvIHJlc29sdmUgZGF0YSBtYW5pcHVsYXRpb24gZGlmZmljdWx0aWVzIApsaWJyYXJ5KEhtaXNjKSAgICAgICAgICAgICMgdXNlZnVsIGZ1bmN0aW9ucyBmb3IgZGF0YSBhbmFseXNpcyBhbmQgaGlnaCAtIGxldmVsIGdyYXBoaWNzCmxpYnJhcnkoZm9yZWlnbikgICAgICAgICAgIyByZWFkIGRhdGEgc3RvcmVkIGJ5IE1pbml0YWIsIFNQU1MsIFN0YXRhCmxpYnJhcnkob3Blbnhsc3gpICAgICAgICAgIyBvcGVuLCByZWFkLCB3cml0ZSxhbmQgZWRpdCB4bHN4IGZpbGVzIApsaWJyYXJ5KHRpZHl2ZXJzZSkgICAgICAgICMgY29sbGVjdGlvbiBvZiBSIHBhY2thZ2VzIGRlc2lnbmVkIGZvciBkYXRhIHNjaWVuY2UKCiMgdmlzdWFsaXphdGlvbiAKbGlicmFyeShnZ21hcCkgICAgICAgICAgICAjIHNwYXRpYWwgZGF0YSB2aXN1YWxpemF0aW9uIApsaWJyYXJ5KHJnZW9kYSkgICAgICAgICAgICMgc3BhdGlhbCBkYXRhIGFuYWx5c2lzIGJhc2VkIG9uIHNvZnR3YXJlIEdlb0RhCmxpYnJhcnkoZ2dwbG90MikgICAgICAgICAgIyBHcmFtbWFyIG9mIGdyYXBoaWNzLiBTeXN0ZW0gZm9yIGRlY2xhcmF0aXZlIGNyZWF0aW5nIGdyYXBoaWNzCmxpYnJhcnkoY29ycnBsb3QpICAgICAgICAgIyBwcm92aWRlcyBhIHZpc3VhbCBleHBsb3JhdG9yeSB0b29sIG9uIGNvcnJlbGF0aW9uIG1hdHJpeApsaWJyYXJ5KFJDb2xvckJyZXdlcikgICAgICMgb2ZmZXJzIHNldmVyYWwgY29sb3IgcGFsZXR0ZXMKbGlicmFyeShsZWFmbGV0KSAgICAgICAgICAjIGludGVyYWN0aXZlIG1hcHMKbGlicmFyeShsZWFmc3luYykgICAgICAgICAjIGNyZWF0ZSBzbWFsbCBtdWx0aXBsZXMgb2Ygc2V2ZXJhbCBsZWFmbGV0IHdlYiBtYXBzCmxpYnJhcnkoaHRtbHRvb2xzKSAgICAgICAgIyB0b29scyBmb3IgSFRNTCBnZW5lcmF0aW9uIGFuZCBvdXRwdXQgCgojIG90aGVycyAKbGlicmFyeShybGFuZykgICAgICAgICAgICAjIGNvbGxlY3Rpb24gb2YgZnJhbWV3b3JrcyBhbmQgQVBJcyBmb3IgcHJvZ3JhbW1pbmcgd2l0aCBSCmxpYnJhcnkoY2xhc3NJbnQpICAgICAgICAgIyBtZXRob2RzIGZvciBjaG9vc2luZyB1bml2YXJpYXRlIGNsYXNzIGludGVydmFscyBmb3IgbWFwcGluZyBvciBvdGhlciBncmFwaGljIHB1cnBvc2VzCmxpYnJhcnkoZ3JpZEV4dHJhKSAgICAgICAgIyB0byBhcnJhbmdlIGFuZCBjb21iaW5lIHBsb3RzIGZvciBlYXN5IGNvbXBhcmlzb24KbGlicmFyeShrbml0cikgICAgICAgICAgICAjIGludGVncmF0ZXMgY29tcHV0aW5nIGFuZCByZXBvcnRpbmcKCiMgR29vZ2xlIE1hcHMgQVBJCmxpYnJhcnkoZ29vZ2xld2F5KSAgICAgICAgIyBwcm92aWRlcyBhIG1lY2hhbmlzbSB0byBhY2Nlc3MgdmFyaW91cyBHb29nbGUgTWFwcyBBUElzLCBpbmNsdWRpbmcgcGxvdHRpbmcgYSBHb29nbGUgTWFwIGZyb20gUiBhbmQgb3ZlcmxheWluZyBpdCB3aXRoIHNoYXBlcyBhbmQgbWFya2VycywgYW5kIHJldHJpZXZpbmcgZGF0YSBmcm9tIHRoZSBwbGFjZXMsIGRpcmVjdGlvbnMsIHJvYWRzLCBkaXN0YW5jZXMsIGdlb2NvZGluZywgZWxldmF0aW9uIGFuZCB0aW1lem9uZSBBUElzCgpsaWJyYXJ5KHRtKSAgIyBBc2Vnw7pyYXRlIGRlIGNhcmdhciBlc3RlIHBhcXVldGUgYW50ZXMgZGUgdXNhciAnQ29ycHVzJwoKYGBgCgojIyAgKjEuIENsYXZlIGRlIEdvb2dsZSBNYXBzIEFQSSoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZ21hcHNfa2V5IDwtICdBSXphU3lETXRrSUV2VXBGY2N5VUNHeExnWE8tVHpUY0VSZnpKM28nCnJlZ2lzdGVyX2dvb2dsZShrZXkgPSBnbWFwc19rZXkpCmBgYAoKIyMgKjIuIFBhcsOhbWV0cm9zIGluaWNpYWxlcyBkZSBiw7pzcXVlZGEqCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxhdGl0dWRlIDwtIDI1LjY2NjcKbG9uZ2l0dWRlIDwtIC0xMDAuMjg5NQpyYWRpbyA8LSAxNTAwMCAjMTUga20sIGVzdMOhIGVuIG1ldHJvcwojIENvb3JkZW5hZGFzIGRlbCBwdW50byBkZSBvcmlnZW4sIFRFQzogMjUuNjY2NzI4NzQ5NTI0MzIsIC0xMDAuMjg5NTM5OTk5ODMyMTIKYGBgCgoKIyMgKjMuIENvbnN1bHRhIGNvbiBHb29nbGUgUGxhY2VzIEFQSTogQ2Fmw6lzIGVuIE1vbnRlcnJleSoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBDb29yZGVuYWRhcyBkZWwgcHVudG8gZGUgb3JpZ2VuLCBURUM6IDI1LjY2NjcyODc0OTUyNDMyLCAtMTAwLjI4OTUzOTk5OTgzMjEyCiMgQ29uc3VsdGEgY29uIEdvb2dsZSBQbGFjZXMgQVBJOiBDYWbDqXMgZW4gTW9udGVycmV5IChTb2xvIGNvbiByZXN1bHRhZG9zIGRlIGxhIHByaW1lcmEgcMOhZ2luYSkKc2VhcmNoX3Jlc3VsdHNfMSA8LSBnb29nbGVfcGxhY2VzKHNlYXJjaF9zdHJpbmcgPSAnY2FmZScsIGxvY2F0aW9uPWMobGF0aXR1ZGUsbG9uZ2l0dWRlKSwgcmFkaXVzPXJhZGlvLCBrZXk9Z21hcHNfa2V5KQpgYGAKCiMjICo0LiBDcmVhY2nDs24gZGUgYmFzZSBkZSBkYXRvcyoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KY2FmZXMgPC0gc2VhcmNoX3Jlc3VsdHNfMSRyZXN1bHRzJG5hbWUKYnVzaW5lc3NfcmF0aW5nIDwtIHNlYXJjaF9yZXN1bHRzXzEkcmVzdWx0cyRyYXRpbmcKdXNlcl9yYXRpbmdzX3RvdGFsIDwtIHNlYXJjaF9yZXN1bHRzXzEkcmVzdWx0cyR1c2VyX3JhdGluZ3NfdG90YWwKcGxhY2VfaWQgPC0gc2VhcmNoX3Jlc3VsdHNfMSRyZXN1bHRzJHBsYWNlX2lkCmxhdCA8LSBzZWFyY2hfcmVzdWx0c18xJHJlc3VsdHMkZ2VvbWV0cnkkbG9jYXRpb24kbGF0CmxvbiA8LSBzZWFyY2hfcmVzdWx0c18xJHJlc3VsdHMkZ2VvbWV0cnkkbG9jYXRpb24kbG5nCgpkYXRhIDwtIGRhdGEuZnJhbWUoY2FmZXMsIGJ1c2luZXNzX3JhdGluZywgdXNlcl9yYXRpbmdzX3RvdGFsLCBwbGFjZV9pZCwgbGF0LCBsb24pCgpgYGAKCiMjICo1LiBUb3AgeSBCb3R0b20gbmVnb2Npb3MqCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CgpkYXRhX3RvcCA8LSBkYXRhICU+JSBzbGljZV9tYXgoYnVzaW5lc3NfcmF0aW5nLCBuID0gMTApCmRhdGFfYm90dG9tIDwtIGRhdGEgJT4lIHNsaWNlX21pbihidXNpbmVzc19yYXRpbmcsIG4gPSAxMCkKYGBgCgojIyAqNi4gVmlzdWFsaXphY2nDs24gZW4gbWFwYSBpbnRlcmFjdGl2byoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGVhZmxldChkYXRhX3RvcCkgJT4lIGFkZFRpbGVzKCkgJT4lCiAgYWRkQ2lyY2xlTWFya2Vycyh+bG9uLCB+bGF0LCBwb3B1cCA9IH5jYWZlcywgY29sb3IgPSAiZ3JlZW4iLCByYWRpdXMgPSAxNSkKYGBgCgoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGVhZmxldChkYXRhX2JvdHRvbSkgJT4lIGFkZFRpbGVzKCkgJT4lCiAgYWRkQ2lyY2xlTWFya2Vycyh+bG9uLCB+bGF0LCBwb3B1cCA9IH5jYWZlcywgY29sb3IgPSAicmVkIiwgcmFkaXVzID0gMTUpCmBgYAoKIyMgKjcuIEFuw6FsaXNpcyBkZSBTZW50aW1pZW50byAoU2VudGltZW50IEFuYWx5c2lzKSoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KcmV2aWV3c190b3AgPC0gZ29vZ2xlX3BsYWNlX2RldGFpbHMocGxhY2VfaWQgPSBkYXRhX3RvcCRwbGFjZV9pZFsxXSwga2V5ID0gZ21hcHNfa2V5KQpyZXZpZXdzX2JvdCA8LSBnb29nbGVfcGxhY2VfZGV0YWlscyhwbGFjZV9pZCA9IGRhdGFfYm90dG9tJHBsYWNlX2lkWzFdLCBrZXkgPSBnbWFwc19rZXkpCnJldmlld3NfdG9wCmBgYAoKIyMgKlRvcHMgeSBCb3R0b21zKgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIFRPUCA1IE1FSk9SIFZBTFVBRE9TCnRvcDUgPC0gZGF0YSAlPiUKICBhcnJhbmdlKGRlc2MoYnVzaW5lc3NfcmF0aW5nKSkgJT4lCiAgc2xpY2VfaGVhZChuID0gNSkKCmdncGxvdCh0b3A1LCBhZXMoeCA9IHJlb3JkZXIoY2FmZXMsIGJ1c2luZXNzX3JhdGluZyksIHkgPSBidXNpbmVzc19yYXRpbmcpKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJkYXJrZ3JlZW4iKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVG9wIDUgQ2Fmw6lzIE1lam9yIFZhbHVhZG9zIiwKICAgIHggPSAiU3VjdXJzYWwiLAogICAgeSA9ICJDYWxpZmljYWNpw7NuIChtw6F4LiA1KSIKICApICsKICB5bGltKDAsIDUpICsKICB0aGVtZV9taW5pbWFsKCkKCiMgQk9UVE9NIDUgUEVPUiBWQUxVQURPUwpib3R0b201IDwtIGRhdGEgJT4lCiAgYXJyYW5nZShidXNpbmVzc19yYXRpbmcpICU+JQogIHNsaWNlX2hlYWQobiA9IDUpCgpnZ3Bsb3QoYm90dG9tNSwgYWVzKHggPSByZW9yZGVyKGNhZmVzLCBidXNpbmVzc19yYXRpbmcpLCB5ID0gYnVzaW5lc3NfcmF0aW5nKSkgKwogIGdlb21fY29sKGZpbGwgPSAiYnJvd24zIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCA1IENhZsOpcyBQZW9yIFZhbHVhZG9zIiwKICAgIHggPSAiU3VjdXJzYWwiLAogICAgeSA9ICJDYWxpZmljYWNpw7NuIChtw6F4LiA1KSIKICApICsKICB5bGltKDAsIDUpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojICpQYXJ0ZSBCOiBBbsOhbGlzaXMgZGUgUGVyY2VwY2nDs24gZGVsIENsaWVudGUgKFNlbnRpbWVudCBBbmFseXNpcykqCiMjICo4LiBXb3JkY2xvdWQqCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodG0pCmxpYnJhcnkod29yZGNsb3VkKSAgIyBDYXJnYXIgbGEgbGlicmVyw61hICd3b3JkY2xvdWQnCgojIENvbWVudGFyaW9zIGRlIGxvcyBuZWdvY2lvcyBtZWpvciB2YWxvcmFkb3MKdG9wX3RleHQgPC0gcmV2aWV3c190b3AkcmVzdWx0JHJldmlld3MkdGV4dAoKdG9wX2NvcnB1cyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRvcF90ZXh0KSkKdG9wX2NvcnB1cyA8LSB0bV9tYXAodG9wX2NvcnB1cywgY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKdG9wX2NvcnB1cyA8LSB0bV9tYXAodG9wX2NvcnB1cywgcmVtb3ZlUHVuY3R1YXRpb24pCnRvcF9jb3JwdXMgPC0gdG1fbWFwKHRvcF9jb3JwdXMsIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoInNwYW5pc2giKSkKd29yZGNsb3VkKHRvcF9jb3JwdXMsIG1heC53b3Jkcz0xMDAsIHJhbmRvbS5vcmRlcj1GQUxTRSwgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpCmBgYAoKCiMjICo4LjEgV29yZGNsb3VkKgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIENvbWVudGFyaW9zIGRlIGxvcyBuZWdvY2lvcyBwZW9yIHZhbG9yYWRvcwpib3RfdGV4dCA8LSByZXZpZXdzX2JvdCRyZXN1bHQkcmV2aWV3cyR0ZXh0Cgp0b3BfY29ycHVzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodG9wX3RleHQpKQp0b3BfY29ycHVzIDwtIHRtX21hcCh0b3BfY29ycHVzLCBjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQp0b3BfY29ycHVzIDwtIHRtX21hcCh0b3BfY29ycHVzLCByZW1vdmVQdW5jdHVhdGlvbikKdG9wX2NvcnB1cyA8LSB0bV9tYXAodG9wX2NvcnB1cywgcmVtb3ZlV29yZHMsIHN0b3B3b3Jkcygic3BhbmlzaCIpKQp3b3JkY2xvdWQodG9wX2NvcnB1cywgbWF4LndvcmRzPTEwMCwgcmFuZG9tLm9yZGVyPUZBTFNFLCBjb2xvcnM9YnJld2VyLnBhbCg4LCAiRGFyazIiKSkKCiMgQ29tZW50YXJpb3MgZGUgbG9zIG5lZ29jaW9zIHBlb3IgdmFsb3JhZG9zCmJvdF90ZXh0IDwtIHJldmlld3NfYm90JHJlc3VsdCRyZXZpZXdzJHRleHQKCmJvdF9jb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZShib3RfdGV4dCkpCmJvdF9jb3JwdXMgPC0gdG1fbWFwKGJvdF9jb3JwdXMsIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpCmJvdF9jb3JwdXMgPC0gdG1fbWFwKGJvdF9jb3JwdXMsIHJlbW92ZVB1bmN0dWF0aW9uKQoKYGBgCgoKIyMgKjkuIEFuw6FsaXNpcyBkZSBTZW50aW1pZW50byoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShzeXV6aGV0KQoKIyBBbsOhbGlzaXMgZGUgc2VudGltaWVudG9zIHBhcmEgbG9zIGNvbWVudGFyaW9zIGRlIGxvcyBuZWdvY2lvcyBtZWpvciB5IHBlb3IgdmFsb3JhZG9zCnRvcF9zZW50aW1lbnQgPC0gZ2V0X25yY19zZW50aW1lbnQodG9wX3RleHQpCmJvdF9zZW50aW1lbnQgPC0gZ2V0X25yY19zZW50aW1lbnQoYm90X3RleHQpCgojIFZpc3VhbGl6YWNpw7NuIGRlIGVtb2Npb25lcyBkZSBsb3MgbmVnb2Npb3MgbWVqb3IgdmFsb3JhZG9zCmJhcnBsb3QoY29sU3Vtcyh0b3Bfc2VudGltZW50KSwgbGFzPTIsIGNvbD0iYmx1ZSIsIG1haW49IkVtb2Npb25lcyAtIE5lZ29jaW9zIGNvbiBtZWpvciBjYWxpZmljYWNpw7NuIikKCiMgVmlzdWFsaXphY2nDs24gZGUgZW1vY2lvbmVzIGRlIGxvcyBuZWdvY2lvcyBwZW9yIHZhbG9yYWRvcwpiYXJwbG90KGNvbFN1bXMoYm90X3NlbnRpbWVudCksIGxhcz0yLCBjb2w9InJlZCIsIG1haW49IkVtb2Npb25lcyAtIE5lZ29jaW9zIGNvbiBwZW9yIGNhbGlmaWNhY2nDs24iKQoKYGBgCgoKIyMgKjEwLiBEaXN0cmlidWNpw7NuIGRlbCBTZW50aW1lbnQgU2NvcmUqCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgT2J0ZW5lciB2ZWN0b3IgZGUgdGV4dG8gbGltcGlvCmJvdF92ZWN0b3IgPC0gc2FwcGx5KGJvdF9jb3JwdXMsIGFzLmNoYXJhY3RlcikKCiMgU2VudGltZW50IHNjb3JlCmJvdF9zY29yZXMgPC0gZ2V0X3NlbnRpbWVudChib3RfdmVjdG9yLCBtZXRob2QgPSAic3l1emhldCIpCgojIE1vc3RyYXIgZGlzdHJpYnVjacOzbgpoaXN0KGJvdF9zY29yZXMsCiAgICAgYnJlYWtzID0gMTAsCiAgICAgY29sID0gInN0ZWVsYmx1ZSIsCiAgICAgbWFpbiA9ICJEaXN0cmlidWNpw7NuIGRlbCBTZW50aW1lbnQgU2NvcmUiLAogICAgIHhsYWIgPSAiU2VudGltZW50IFNjb3JlIikKCmBgYAoKIyMgKjExLiBEaXN0cmlidWNpw7NuIFBvc2l0aXZvLCBOZWdhdGl2bywgTmV1dHJhbCoKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmdldF9zZW50aW1lbnRfc3VtbWFyeSA8LSBmdW5jdGlvbih0ZXh0KSB7CiAgc2VudGltZW50X3Njb3JlcyA8LSBnZXRfc2VudGltZW50KHRleHQsIG1ldGhvZCA9ICJzeXV6aGV0IikKICBzdW1tYXJ5IDwtIHRhYmxlKGN1dChzZW50aW1lbnRfc2NvcmVzLCBicmVha3M9YygtSW5mLCAtMC4xLCAwLjEsIEluZiksIGxhYmVscz1jKCJOZWdhdGl2byIsICJOZXV0cmFsIiwgIlBvc2l0aXZvIikpKQogIHJldHVybihzdW1tYXJ5KQp9CmdldF9zZW50aW1lbnRfc3VtbWFyeSh0b3BfdGV4dCkKZ2V0X3NlbnRpbWVudF9zdW1tYXJ5KGJvdF90ZXh0KQpgYGAKIyMgQ29uY2x1c2lvbmVzCi0gTG9zIGNhZsOpcyBtZWpvciB2YWxvcmFkb3MgdGllbmVuIHVuYSBjYWxpZmljYWNpw7NuIHN1cGVyaW9yIGEgNC4wLCBtaWVudHJhcyBxdWUgbG9zIHBlb3JlcyBuZWdvY2lvcyB0aWVuZW4gY2FsaWZpY2FjaW9uZXMgcG9yIGRlYmFqbyBkZSAyLjUsIGxvIHF1ZSBpbmRpY2EgdW5hIGdyYW4gZGlzcGFyaWRhZCBlbiBsYXMgcHJlZmVyZW5jaWFzIGRlIGxvcyBjbGllbnRlcy4KLSBFc3RvcyBleHRyZW1vcyBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgc3VnaWVyZW4gcXVlIGVsIHNlcnZpY2lvIHkgbGEgY2FsaWRhZCBkZSBsb3MgcHJvZHVjdG9zIHNvbiBmYWN0b3JlcyBjbGF2ZSBlbiBsYSBwZXJjZXBjacOzbiBkZWwgY2xpZW50ZS4gTG9zIG5lZ29jaW9zIGVuIGVsIHRvcCAxMCB0aWVuZGVuIGEgc2VyIG11eSBjb25zaXN0ZW50ZXMgZW4gbGEgc2F0aXNmYWNjacOzbiBkZSBzdXMgY2xpZW50ZXMuCi0gTG9zIG5lZ29jaW9zIG1lam9yIHZhbG9yYWRvcyBlc3TDoW4gZGlzdHJpYnVpZG9zIGRlIG1hbmVyYSBtw6FzIGhvbW9nw6luZWEgZW4gw6FyZWFzIGNlbnRyYWxlcyBkZSBNb250ZXJyZXksIG1pZW50cmFzIHF1ZSBsb3MgbmVnb2Npb3MgcGVvciB2YWxvcmFkb3Mgc3VlbGVuIGNvbmNlbnRyYXJzZSBlbiDDoXJlYXMgcGVyaWbDqXJpY2FzIG8gbWVub3MgdHJhbnNpdGFkYXMsIGxvIHF1ZSBwb2Ryw61hIGluZGljYXIgdW5hIHJlbGFjacOzbiBlbnRyZSBsYSBsb2NhbGl6YWNpw7NuIHkgbGEgY2FsaWRhZCBwZXJjaWJpZGEgcG9yIGxvcyBjbGllbnRlcy4KLSBFbCBhbsOhbGlzaXMgZGUgbG9zIHNlbnRpbWVudCBzY29yZXMgbXVlc3RyYSBxdWUgbG9zIG5lZ29jaW9zIG1lam9yIHZhbG9yYWRvcyB0aWVuZW4gdW5hIGRpc3RyaWJ1Y2nDs24gcG9zaXRpdmEgZGUgbG9zIHNlbnRpbWllbnRvcywgY29uIHB1bnR1YWNpb25lcyBxdWUgc2UgYWdydXBhbiBjZXJjYSBkZWwgcmFuZ28gcG9zaXRpdm8gKCswLjEgYSArMC41KS4KLSBFbiBjYW1iaW8sIGxvcyBuZWdvY2lvcyBwZW9yIHZhbG9yYWRvcyB0aWVuZW4gdW4gc2VudGltZW50IHNjb3JlIG5lZ2F0aXZvLCBsbyBxdWUgaW5kaWNhIHVuYSBwZXJjZXBjacOzbiBnZW5lcmFsIGRlc2Zhdm9yYWJsZSwgY29uIHVuYSBjb25jZW50cmFjacOzbiBkZSBwdW50dWFjaW9uZXMgZW4gZWwgcmFuZ28gbmVnYXRpdm8gKC0wLjEgYSAtMC41KS4KLSBMb3MgbmVnb2Npb3MgY29uIG1lbm9yIHB1bnR1YWNpw7NuIHBvZHLDrWFuIG1lam9yYXIgZW4gw6FyZWFzIGNyw610aWNhcyBjb21vIGVsIHNlcnZpY2lvIGFsIGNsaWVudGUsIGxhIGNhbGlkYWQgZGVsIHByb2R1Y3RvIHkgbGEgYXRlbmNpw7NuIGVuIGdlbmVyYWwuCi0gTG9zIGNvbWVudGFyaW9zIG5lZ2F0aXZvcyBzb2JyZSBsYSB0ZW1wZXJhdHVyYSBkZSBsYXMgYmViaWRhcywgdGllbXBvIGRlIGVzcGVyYSB5IGFjdGl0dWQgZGVsIHBlcnNvbmFsIHN1Z2llcmVuIHF1ZSBsYSBlZmljaWVuY2lhIHkgbGEgY2FsaWRhZCBkZWwgc2VydmljaW8gc29uIMOhcmVhcyBjbGF2ZSBwYXJhIG1lam9yYXIuCi0gTG9zIG5lZ29jaW9zIG1lam9yIHZhbG9yYWRvcyB0aWVuZGVuIGEgdGVuZXIgdW4gbsO6bWVybyBzaWduaWZpY2F0aXZhbWVudGUgbWF5b3IgZGUgcmVzZcOxYXMgcXVlIGxvcyBwZW9yIHZhbG9yYWRvcy4gRXN0byBwb2Ryw61hIGluZGljYXIgcXVlIGxhIHJlcHV0YWNpw7NuIHBvc2l0aXZhIGRlIGVzdG9zIG5lZ29jaW9zIGF0cmFlIGEgbcOhcyBjbGllbnRlcyBkaXNwdWVzdG9zIGEgZGVqYXIgc3UgcmVzZcOxYS4KLSBMb3MgbmVnb2Npb3MgbWVqb3IgdmFsb3JhZG9zIHN1ZWxlbiB0ZW5lciB1bmEgbWF5b3IgY29uc2lzdGVuY2lhIGVuIGxhcyByZXNlw7FhcyBwb3NpdGl2YXMsIG1pZW50cmFzIHF1ZSBsb3MgbmVnb2Npb3MgcGVvciB2YWxvcmFkb3MgcHJlc2VudGFuIHVuYSBncmFuIHZhcmlhYmlsaWRhZCBlbiBsYXMgb3BpbmlvbmVzLCBsbyBxdWUgcG9kcsOtYSBpbmRpY2FyIHF1ZSBsYSBjYWxpZGFkIGRlbCBzZXJ2aWNpbyBlcyBpbmNvbnNpc3RlbnRlLgotIFBhcmEgbG9zIG5lZ29jaW9zIHBlb3IgdmFsb3JhZG9zLCB1bmEgaW50ZXJ2ZW5jacOzbiBjZW50cmFkYSBlbiBtZWpvcmFyIGVsIHNlcnZpY2lvIGFsIGNsaWVudGUgeSBsYSBjYWxpZGFkIGRlbCBwcm9kdWN0byBwb2Ryw61hIGVsZXZhciBzaWduaWZpY2F0aXZhbWVudGUgbGEgcGVyY2VwY2nDs24gZGUgbG9zIGNsaWVudGVzLgotIEV2YWx1YXIgbGEgYWNjZXNpYmlsaWRhZCB5IHViaWNhY2nDs24gZGUgbG9zIG5lZ29jaW9zIHBlb3IgdmFsb3JhZG9zIHBvZHLDrWEgc2VyIHJlbGV2YW50ZSwgZGFkbyBxdWUgYWxndW5vcyBwb2Ryw61hbiBlc3RhciBlbiB6b25hcyBjb24gbWVub3IgYWZsdWVuY2lhIGRlIGNsaWVudGVzLgo=