sugitora commited on
Commit
53b9ac3
·
verified ·
1 Parent(s): 64491a0

Upload 5 files

Browse files
Dockerfile CHANGED
@@ -1,14 +1,21 @@
1
- FROM rocker/r-base:latest
 
 
2
 
3
- WORKDIR /code
 
4
 
5
- RUN install2.r --error \
6
- shiny \
7
- dplyr \
8
- ggplot2 \
9
- readr \
10
- ggExtra
11
-
12
- COPY . .
13
 
14
- CMD ["R", "--quiet", "-e", "shiny::runApp(host='0.0.0.0', port=7860)"]
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face Spaces用 R Shiny Dockerfile
2
+ # rocker/geospatial: leaflet, dplyr等が事前インストール済み
3
+ FROM rocker/geospatial:4.4.1
4
 
5
+ # shinyをインストール
6
+ RUN R -e "install.packages('shiny', repos='https://cloud.r-project.org/')"
7
 
8
+ # パッケージ確認
9
+ RUN R -e "library(shiny); library(dplyr); library(leaflet); cat('All packages OK\n')"
 
 
 
 
 
 
10
 
11
+ # アプリディレクトリ
12
+ WORKDIR /app
13
+
14
+ # ファイルをコピー(新しいデータファイル名に対応)
15
+ COPY app.R ac_contract_list_geocoded.csv ac_guard_master_geocoded.csv ac_availability.csv /app/
16
+
17
+ # ポート設定
18
+ EXPOSE 7860
19
+
20
+ # 実行
21
+ CMD ["R", "-e", "shiny::runApp('/app', host='0.0.0.0', port=7860)"]
ac_availability.csv ADDED
The diff for this file is too large to render. See raw diff
 
ac_contract_list_geocoded.csv ADDED
The diff for this file is too large to render. See raw diff
 
ac_guard_master_geocoded.csv ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ユーザー番号,従業員番号,ユーザーID,苗字,名前,苗字カナ,名前カナ,所属支店,生年月日,年齢,性別,血液型,最低血圧,最高血圧,郵便番号,住所,本籍,最寄り駅,交通手段,電話番号1,電話番号2,緊急連絡先(氏名),続柄,緊急連絡先(電話番号),確認日,緊急連絡先(氏名)2,続柄2,緊急連絡先(電話番号)2,確認日2,緊急連絡先(氏名)3,続柄3,緊急連絡先(電話番号)3,確認日3,扶養家族人数,配偶者の有無,メールアドレス,入社日,home_lat,home_lng
2
+ 375,u00016,u00016,,,,,栃木・群馬,,,,,,,321-0152,栃木県宇都宮市西川田6-4-18,,西川田,車,,,,,,,,,,,,,,,,,,42761,36.5551,139.8828
3
+ 391,u00033,u00033,,,,,栃木・群馬,,,,,,,321-0974,栃木県宇都宮市竹林町123 クレセントレジデンスC202,秋田県大館市釈迦内字山神台1-2,駅東公園前,車,,,,,028-627-6584,,,,028-627-6584,,,,,,,,,43498,36.5551,139.8828
4
+ 397,u00039,u00039,,,,,栃木・群馬,,,,,,,322-0045,栃木県鹿沼市上殿町373-1,栃木県鹿沼市上殿町373-1,新鹿沼,車,,,,,090-2245-5253,,,,090-2245-5253,,,,,,,,,43655,36.567,139.746
5
+ 401,u00043,u00043,,,,,栃木・群馬,,,,,,,321-0139,栃木県宇都宮市若松原2-18-9,,雀宮,車,,,,,080-6548-1226,,,,080-6548-1226,,,,,,,,,43783,36.5551,139.8828
6
+ 412,u00054,u00054,,,,,栃木・群馬,,,,,,,324-0031,栃木県大田原市藤沢363,,片岡,車,,,,,080-1683-8271,,,,080-1683-8271,,,,,,,,,44096,36.8717,140.015
7
+ 422,u00064,u00064,,,,,栃木・群馬,,,,,,,321-0952,栃木県宇都宮市泉が丘6-2-17  アザレヤマンション206,栃木県宇都宮市泉が丘6-2-17  アザレヤマンション206,峰,車,,,,,090-9675-7861,,,,090-9675-7861,,,,,,,,,44324,36.5551,139.8828
8
+ 423,u00065,u00065,,,,,栃木・群馬,,,,,,,321-0952,栃木県宇都宮市泉が丘6-2-17  アザレアマンション206,栃木県宇都宮市泉が丘6-2-17  アザレアマンション206,峰,車,,,,,095-844-6043,,,,095-844-6043,,,,,,,,,44324,36.5551,139.8828
9
+ 440,u00082,u00082,,,,,栃木・群馬,,,,,,,329-1233,栃木県塩谷郡高根沢町宝積寺2248-32,,宝積寺,車,,,,,028-675-2766,,,,028-675-2766,,,,,,,,,44629,36.6333,139.9833
10
+ 447,u00089,u00089,,,,,栃木・群馬,,,,,,,322-0036,栃木県鹿沼市下田町2-1403-16,栃木県鹿沼市下田町2-1403-16,新鹿沼,車,,,,,0289-62-3256,,,,0289-62-3256,,,,,,,,,44819,36.567,139.746
11
+ 449,U00091,u00091,,,,,栃木・群馬,,,,,,,321-0111,栃木県宇都宮市川田町1261-3 沢村ハイツ101,,南宇都宮,車,,,,,090-8814-0030,,,,090-8814-0030,,,,,,,,,44887,36.5551,139.8828
12
+ 450,u00092,u00092,,,,,栃木・群馬,,,,,,,321-3426,栃木県芳賀郡市貝町赤羽418-27,,多田羅,車,,,,,090-2620-7084,,,,090-2620-7084,,,,,,,,,45026,36.5167,140.0833
13
+ 451,u00093,u00093,,,,,栃木・群馬,,,,,,,321-0982,栃木県宇都宮市御幸ケ原町143-19 サンビレッジ御幸ヶ原A203,,峰,車,,,,,080-2305-7654,,,,080-2305-7654,,,,,,,,,45178,36.5551,139.8828
14
+ 1022,u00108,k000162,,,,,栃木・群馬,,,,,,,321-0932,栃木県宇都宮市平松本町364 県住541,,駅東公園前,車,,,,,080-6111-5952,,,,080-6111-5952,,,,,,,,,45541,36.5551,139.8828
15
+ 1050,u00109,k000190,,,,,栃木・群馬,,,,,,,321-0925,栃木県宇都宮市東簗瀬1丁目42番地4 レクエルドユーミー301,埼玉県秩父市上影森31-1,宇都宮,車,,,,,0494-24-5432,,,,0494-24-5432,,,,,,,,,45545,36.5551,139.8828
16
+ 1147,u00114,k000267,,,,,栃木・群馬,,,,,,,321-0236,栃木県下都賀郡壬生町上稲葉1976-2,,東武金崎,車,,,,,080-6757-6348,,,,080-6757-6348,,,,,,,,,45591,36.4258,139.8083
17
+ 1148,u00115,k000268,,,,,栃木・群馬,,,,,,,321-4337,栃木県真岡市上高間木1-7-2 スカイヒルズC-102,,真岡駅,車,,,,,090-5337-9153,,,,090-5337-9153,,,,,,,,,45474,36.4403,140.0148
18
+ 1241,u00116,k000361,,,,,栃木・群馬,,,,,,,329-1104,栃木県宇都宮市下岡本町1949番地5,栃木県宇都宮市下岡本町1949番地5,岡本駅,車,,,,,090-4535-8389,45682.0,,,090-4535-8389,,,,,,,,,45600,36.5551,139.8828
19
+ 1350,u00061,k000458,,,,,栃木・群馬,,,,,,,322-0031,栃木県鹿沼市睦町320睦町市営住宅3-5,栃木県鹿沼市茂呂1858番地18,鹿沼,車,,,,,090-2918-3572,,,,090-2918-3572,,,,,,,,,45772,36.567,139.746
20
+ 1353,E00406,k000461,,,,,栃木・群馬,,,,,,,321-3423,栃木県芳賀郡市貝町市塙1215-1,栃木県宇都宮市屋板町529番地1,市塙,車,,,,,090-9016-3608,,,,090-9016-3608,,,,,,,,,45785,36.5167,140.0833
21
+ 1415,E00413,k000523,,,,,栃木・群馬,,,,,,,322-0344,栃木県鹿沼市西沢町324番地,栃木県鹿沼市西沢町324番地,樅山,車,,,,,090-8894-0993,,,,090-8894-0993,,,,,,,,,45930,36.567,139.746
22
+ 1425,F00408,k000533,,,,,栃木・群馬,,,,,,,321-0152,栃木県宇都宮市西川田5丁目27番13号 シャトルハイツA102,栃木県宇都宮市川田町884番地,西川田,車,,,,,090-6658-0525,,,,090-6658-0525,,,,,,,,,45916,36.5551,139.8828
23
+ 1488,F00411,k000568,,,,,栃木・群馬,,,,,,,321-0932,栃木県宇都宮市平松本町364番地 県営平松本町住宅5棟41号 ,栃木県宇都宮市平松本町364番地1 ,駅東公園前,車,,,,,080-5984-9707,,,,080-5984-9707,,,,,,,,,45973,36.5551,139.8828
24
+ 476,E00113,e00113,,,,,栃木・群馬,,,,,,,307-0042,茨城県結城市江川新宿1988番地,,間々田,車,,,,,0296-35-2701,,,,0296-35-2701,,,,,,,,,38844,36.3058,139.8767
25
+ 479,E00347,e00347,,,,,栃木・群馬,,,,,,,329-4412,栃木県栃木市大平町北武井670番地,,栃木,車,,,,,080-1248-7855,,,,080-1248-7855,,,,,,,,,41699,36.3817,139.73
26
+ 482,E00384,e00384,,,,,栃木・群馬,,,,,,,328-0075,栃木県栃木市箱森町11-11,,栃木,車,,,,,0282-24-6701,,,,0282-24-6701,,,,,,,,,44512,36.3817,139.73
27
+ 487,E00391,e00391,,,,,栃木・群馬,,,,,,,307-0037,茨城県結城市東茂呂1639,,間々田,車,,,,,0296-48-0621,,,,0296-48-0621,,,,,,,,,45204,36.3058,139.8767
28
+ 488,F00349,f00349,,,,,栃木・群馬,,,,,,,323-0829,栃木県小山市東城南3丁目4番地2,,小山,車,,,,,080-1041-6718,,,,080-1041-6718,,,,,,,,,42010,36.3147,139.8012
29
+ 494,F00400,f00400,,,,,栃木・群馬,,,,,,,327-0004,栃木県佐野市赤坂町200-6 レジデンス赤坂B棟,,佐野駅,電車,,,,,090-9011-4893,,,,090-9011-4893,,,,,,,,,45204,36.3142,139.5783
30
+ 506,E00349,e00349,,,,,栃木・群馬,,,,,,,329-0205,栃木県小山市間々田871番地2,,間々田,電車,,,,,080-3540-4550,,,,080-3540-4550,,,,,,,,,41706,36.3147,139.8012
31
+ 509,F00306,f00306,,,,,栃木・群馬,,,,,,,328-0054,栃木県栃木市平井町88番地7,,栃木,電車,,,,,090-3576-7883,,,,090-3576-7883,,,,,,,,,40579,36.3817,139.73
32
+ 510,F00326,f00326,,,,,栃木・群馬,,,,,,,307-0001,茨城県結城市大木2377番地1,,小田林,車,,,,,0296-35-1180,,,,0296-35-1180,,,,,,,,,41343,36.3058,139.8767
33
+ 1156,F00407,k000276,,,,,栃木・群馬,,,,,,,323-0826,栃木県小山市雨ケ谷827番地3,,小山駅,車,,,,,090-1552-0266,45604.0,,,090-1552-0266,,,,,,,,,45598,36.3147,139.8012
34
+ 1447,E00416,k000555,,,,,栃木・群馬,,,,,,,329-4304,栃木県栃木市岩舟町静和306番地1,栃木県栃木市岩舟町静和856番地1,静和,車,,,,,090-4598-3000,,,,090-4598-3000,,,,,,,,,45959,36.3817,139.73
35
+ 1454,E00417,k000562,,,,,栃木・群馬,,,,,,,323-0818,栃木県小山市大字塚崎1389番地,栃木県小山市大字塚崎1389番地,間々田,車,,,,,070-3666-5345,,,,070-3666-5345,,,,,,,,,45966,36.3147,139.8012
36
+ 478,E00342,e00342,,,,,栃木・群馬,,,,,,,324-0012,栃木県大田原市南金丸381番地2,,那須塩原,車,,,,,080-1347-5090,,,,080-1347-5090,,,,,,,,,41529,36.8717,140.015
37
+ 480,E00352,e00352,,,,,栃木・群馬,,,,,,,329-1311,栃木県さくら市氏家1806-8,,氏家,車,,,,,,,,,,,,,,,,,,41825,36.6858,139.9673
38
+ 483,E00385,e00385,,,,,栃木・群馬,,,,,,,371-0015,群馬県前橋市三河町2-4-1 ライオンズマンション前橋316号,,前橋,電車,,,,,027-288-2687,,,,027-288-2687,,,,,,,,,44384,36.3911,139.0608
39
+ 490,F00386,f00386,,,,,栃木・群馬,,,,,,,366-0002,埼玉県深谷市下手計1059番地 コスモリヴェール3-B号,,深谷,電車,,,,,080-4141-0426,,,,080-4141-0426,,,,,,,,,44354,36.1975,139.2814
40
+ 491,F00390,f00390,,,,,栃木・群馬,,,,,,,320-0056,栃木県宇都宮市戸祭3-8-17 グリーンプラザ202,,東武宇都宮,車,,,,,090-4941-5349,,,,090-4941-5349,,,,,,,,,44798,36.5551,139.8828
41
+ 496,F00402,f00402,,,,,栃木・群馬,,,,,,,370-0844,群馬県高崎市和田多中町13-19,,南高崎,徒歩,,,,,027-325-3623,,,,027-325-3623,,,,,,,,,45331,36.3219,139.0032
42
+ 497,M00017,m00017,,,,,栃木・群馬,,,,,,,370-0852,群馬県高崎市中居町2丁目22番地1 県住F棟151号,,倉賀野,車,,,,,027-253-4464,,,,027-253-4464,,,,,,,,,40088,36.3219,139.0032
43
+ 498,M00021,m00021,,,,,栃木・群馬,,,,,,,370-0004,群馬県高崎市井野町16番地4 吉田アパート104号,,井野(群馬県),車,,,,,0273-64-3485,,,,0273-64-3485,,,,,,,,,40138,36.3219,139.0032
44
+ 499,M00026,m00026,,,,,栃木・群馬,,,,,,,375-0014,群馬県藤岡市下栗須45番地13,,群馬藤岡,車,,,,,080-6625-1498,,,,080-6625-1498,,,,,,,,,40325,36.2556,139.0736
45
+ 500,M00056,m00056,,,,,栃木・群馬,,,,,,,370-3103,群馬県高崎市箕郷町下芝395番地3,,群馬八幡,車,,,,,090-2629-8848,,,,090-2629-8848,,,,,,,,,41913,36.3219,139.0032
46
+ 501,M00083,m00083,,,,,栃木・群馬,,,,,,,367-0055,埼玉県本庄市若泉2丁目7番10号,,本庄,電車,,,,,090-8586-6388,,,,090-8586-6388,,,,,,,,,43357,36.2433,139.1903
47
+ 502,M00087,m00087,,,,,栃木・群馬,,,,,,,370-1201,群馬県高崎市倉賀野町6387 エトワールナイン201号,,倉賀野,車,,,,,027-327-9065,,,,027-327-9065,,,,,,,,,43613,36.3219,139.0032
48
+ 503,E00355,e00355,,,,,栃木・群馬,,,,,,,321-0132,栃木県宇都宮市雀の宮5丁目6番17号,,雀宮,車,,,,,028-655-3367,,,,028-655-3367,,,,,,,,,41890,36.5551,139.8828
49
+ 504,M00042,m00042,,,,,栃木・群馬,,,,,,,370-0851,群馬県高崎市上中居町263番地1 ハーベスト上中居103,,高崎,徒歩,,,,,011-836-0353,,,,011-836-0353,,,,,,,,,41221,36.3219,139.0032
50
+ 505,E00191,e00191,,,,,栃木・群馬,,,,,,,963-1411,福島県郡山市湖南町舟津849,,上戸(福島県),車,,,,,090-9371-7612,,,,090-9371-7612,,,,,,,,,39284,37.4,140.3597
51
+ 507,M00075,m00075,,,,,栃木・群馬,,,,,,,370-1111,群馬県佐波郡玉村町南玉1012番地6,,新町(群馬県),車,,,,,0270-64-0525,,,,0270-64-0525,,,,,,,,,42980,36.3,139.11
52
+ 508,M00076,m00076,,,,,栃木・群馬,,,,,,,370-0046,群馬県高崎市江木町1142-1 ロイヤル88 2B,,高崎問屋町,徒歩,,,,,080-4129-3321,,,,080-4129-3321,,,,,,,,,43088,36.3219,139.0032
53
+ 511,F00356,f00356,,,,,栃木・群馬,,,,,,,320-0011,栃木県宇都宮市富士見が丘4-4-8 ニュー富士見マンション101,,宇都宮,車,,,,,080-3368-3845,,,,080-3368-3845,,,,,,,,,42567,36.5551,139.8828
54
+ 512,E00393,e00393,,,,,栃木・群馬,,,,,,,329-1104,栃木県宇都宮市下岡本町3766-9,,岡本(栃木県),車,,,,,080-5079-5634,,,,080-5079-5634,,,,,,,,,45371,36.5551,139.8828
55
+ 516,M00096,m00096,,,,,栃木・群馬,,,,,,,370-0873,群馬県高崎市豊岡町1581,,北高崎,車,,,,,090-5430-1906,,,,090-5430-1906,,,,,,,,,45312,36.3219,139.0032
56
+ 1141,E00399,k000261,,,,,栃木・群馬,,,,,,,329-0618,栃木県河内郡上三川町しらさぎ1-23-8,,石橋(栃木県),車,,,,,,,,,,,,,,,,,,45595,36.4417,139.9117
57
+ 1242,E00402,k000362,,,,,栃木・群馬,,,,,,,321-0973,栃木県宇都宮市岩曽町807番地11,静岡県御殿場市川島田698番地4,宇都宮駅,車,,,,,090-2420-3087,45685.0,,,090-2420-3087,,,,,,,,,45682,36.5551,139.8828
58
+ 1252,E00403,k000372,,,,,栃木・群馬,,,,,,,370-0816,群馬県高崎市常盤町127番地1 エトワール高崎常盤町402号,青森県つがる市木造筒木坂松本27番地,高崎駅,徒歩,,,,,046-281-2671,45704.0,,,046-281-2671,,,,,,,,,45700,36.3219,139.0032
59
+ 1273,E00404,k000393,,,,,栃木・群馬,,,,,,,379-0111,群馬県安中市板鼻618番地52,群馬県安中市板鼻618番地52,安中,車,,,,,090-2569-9618,45717.0,,,090-2569-9618,,,,,,,,,45700,36.3306,138.8881
60
+ 1328,E00405,k000436,,,,,栃木・群馬,,,,,,,321-4363,栃木県真岡市亀山104番地12,栃木県真岡市東大島1242番地2,真岡,車,,,,,090-2201-1335,45756.0,,,090-2201-1335,,,,,,,,,45744,36.4403,140.0148
61
+ 1494,E00419,k000574,,,,,栃木・群馬,,,,,,,370-1201,群馬県高崎市倉賀野町1815 シオン桜木201,群馬県高崎市倉賀野町1815番地1 ,倉賀野,電車,,,,,090-9208-9116,,,,090-9208-9116,,,,,,,,,45958,36.3219,139.0032
62
+ 979,W00003,k000119,,,,,栃木・群馬,,,,,,,379-2311,群馬県みどり市笠懸町阿左美484番地10,,阿左美,車,,,,,090-3474-5581,,,,090-3474-5581,,,,,,,,,45503,36.3958,139.2817
63
+ 1128,X00012,k000248,,,,,栃木・群馬,,,,,,,370-3501,群馬県北群馬郡榛東村長岡209,,八木原,車,,,,,090-8493-2106,,,,090-8493-2106,,,,,,,,,45556,36.45,139.0
64
+ 1138,X00013,k000258,,,,,栃木・群馬,,,,,,,373-0832,群馬県太田市富沢町172-6,,細谷(群馬県),車,,,,,0276-38-3754,,,,0276-38-3754,,,,,,,,,45563,36.2917,139.3756
65
+ 1167,W00007,k000287,,,,,栃木・群馬,,,,,,,370-0511,群馬県邑楽郡大泉町北小泉1丁目8−14,群馬県邑楽郡大泉町北小泉1丁目8番,小泉町(群馬県),車,,,,,0276-61-0683,45607.0,,,0276-61-0683,,,,,,,,,45600,36.25,139.4
66
+ 1175,X00015,k000295,,,,,栃木・群馬,,,,,,,370-0522,群馬県邑楽郡大泉町富士1丁目6番21号,群馬県邑楽郡大泉町1丁目1688番地27,西小泉,車,,,,,0276-63-6193,45615.0,,,0276-63-6193,,,,,,,,,45615,36.25,139.4
67
+ 1176,X00017,k000296,,,,,栃木・群馬,,,,,,,360-0831,埼玉県熊谷市久保島811番地1 熊谷玉井住宅B-612,埼玉県熊谷市久保島811番地1,籠原,車,,,,,070-1426-4750,45619.0,,,070-1426-4750,,,,,,,,,45619,36.1472,139.3886
68
+ 1282,W00009,k000402,,,,,栃木・群馬,,,,,,,379-2313,群馬県みどり市笠懸町鹿615番地19,群馬県みどり市笠懸町鹿615番地19,岩宿,車,,,,,090-3405-0272,,,,090-3405-0272,,,,,,,,,45720,36.3958,139.2817
69
+ 1367,X00018,k000475,,,,,栃木・群馬,,,,,,,326-0338,栃木県足利市福居町1511番地8,群馬県桐生市相生町2丁目518番地10,福居,車,,,,,080-3215-0091,,,,080-3215-0091,,,,,,,,,45839,36.3408,139.4496
70
+ 1388,E00408,k000496,,,,,栃木・群馬,,,,,,,326-0824,栃木県足利市八幡町600番地20 県営八幡住宅243,栃木県足利市若草町3番地3 ,野州山辺,車,,,,,080-125-17584,,,,080-125-17584,,,,,,,,,45887,36.3408,139.4496
71
+ 1397,E00410,k000505,,,,,栃木・群馬,,,,,,,377-0003,群馬県渋川市八木原1280番地2 油屋アパート1号室,群馬県渋川市北橘町真壁1634番地58 ,八木原,車,,,,,090-4412-7342,,,,090-4412-7342,,,,,,,,,45894,36.4892,139.0
72
+ 1428,F00414,k000536,,,,,栃木・群馬,,,,,,,370-0883,群馬県高崎市剣崎町414番地10,群馬県高崎市剣崎町414番地10,群馬八幡,車,,,,,090-1100-3025,,,,090-1100-3025,,,,,,,,,45944,36.3219,139.0032
73
+ 392,u00034,u00034,,,,,栃木・群馬,,,,,,,320-0855,栃木県宇都宮市上欠町1231-342,栃木県宇都宮市上欠町1231-342,鶴田,車,,,,,028-648-1660,,,,028-648-1660,,,,,,,,,43517,36.5551,139.8828
74
+ 431,u00073,u00073,,,,,栃木・群馬,,,,,,,320-0075,栃木県宇都宮市宝木本町1148-31,,東武宇都宮,車,,,,,090-5767-9202,,,,090-5767-9202,,,,,,,,,44343,36.5551,139.8828
75
+ 454,u00096,u00096,,,,,栃木・群馬,,,,,,,321-3222,栃木県宇都宮市野高谷町515-2,栃木県さくら市下河戸770,ゆいの杜東,車,,,,,090-7329-1217,,,,090-7329-1217,,,,,,,,,45264,36.5551,139.8828
76
+ 492,F00398,f00398,,,,,栃木・群馬,,,,,,,323-0811,栃木県小山市犬塚3-26-20 ルミエールV102,,,,,,,,090-2022-5821,,,,090-2022-5821,,,,,,,,,45109,36.3147,139.8012
77
+ 493,F00399,f00399,,,,,栃木・群馬,,,,,,,306-0212,茨城県古河市久能1139-1,,,,,,,,090-5339-2813,,,,090-5339-2813,,,,,,,,,45159,36.1947,139.6994
78
+ 1018,k000158,k000158,,,,,栃木・群馬,,,,,,,326-0822,栃木県足利市田中町942-3 サクラマンション301,,足利市,車,,,,,080-5194-8108,,,,080-5194-8108,,,,,,,,,45519,36.3408,139.4496
79
+ 1020,X00010,k000160,,,,,栃木・群馬,,,,,,,326-0141,栃木県足利市小俣町382-3,,小俣(栃木県),車,,,,,090-1460-0858,,,,090-1460-0858,,,,,,,,,45519,36.3408,139.4496
80
+ 1177,X00016,k000297,,,,,栃木・群馬,,,,,,,326-0335,栃木県足利市上渋垂町119番地1,栃木県足利市福富町2013番地1,福居,車,,,,,090-5550-8568,45619.0,,,090-5550-8568,,,,,,,,,45619,36.3408,139.4496
81
+ 1225,E00401,k000345,,,,,栃木・群馬,,,,,,,323-0027,栃木県小山市花垣町1丁目6番29号,栃木県小山市花垣町1丁目6番,小山駅,車,,,,,080-6785-1219,45670.0,,,080-6785-1219,,,,,,,,,45311,36.3147,139.8012
82
+ 1358,E00407,k000466,,,,,栃木・群馬,,,,,,,3200075,栃木県宇都宮市宝木本町1246番地7 アムールアドニスⅡ 201,栃木県日光市土沢1810番地14,東武宇都宮,車,,,,,090-4923-8916,,,,090-4923-8916,,,,,,,,,45821,36.5551,139.8828
83
+ 1391,E00409,k000499,,,,,栃木・群馬,,,,,,,322-0526,栃木県鹿沼市楡木町661番地4,栃木県鹿沼市下奈良部町307番地,楡木,車,,,,,090-7191-7239,,,,090-7191-7239,,,,,,,,,45895,36.567,139.746
84
+ 1412,F00409,k000520,,,,,栃木・群馬,,,,,,,322-0026,栃木県鹿沼市茂呂1175−2 K.U.3A 102,韓国,鹿沼,車,,,,,070-5545-4903,,,,070-5545-4903,,,,,,,,,45922,36.567,139.746
85
+ 1432,E00415,k000540,,,,,栃木・群馬,,,,,,,307-0001,茨城県結城市大字結城10753番地6,茨城県結城市大字結城10753番地6,小田林,車,,,,,080-5505-8698,,,,080-5505-8698,,,,,,,,,45947,36.3058,139.8767
86
+ 1491,E00418,k000571,,,,,栃木・群馬,,,,,,,321-0904,栃木県宇都宮市陽東4-14-40 ひがしハイツワンA101,秋田県鹿角郡小坂町小坂字下前田35-6,陽東3丁目,車,,,,,090-4606-8700,,,,090-4606-8700,,,,,,,,,45978,36.5551,139.8828
87
+ 481,E00362,e00362,,,,,栃木・群馬,,,,,,,323-0014,栃木県小山市喜沢1148番地18,栃木県下野市1657番地24,小山,車,,,,,070-2797-1224,,,,070-2797-1224,,,,,,,,,42786,36.3147,139.8012
88
+ 486,E00389,e00389,,,,,栃木・群馬,,,,,,,320-0053,栃木県宇都宮市戸祭町3018-2 むぎくら第4ハイツB203号室,,,,,,,,090-4636-6540,,,,090-4636-6540,,,,,,,,,45054,36.5551,139.8828
89
+ 763,A01036,a01036,,,,,栃木・群馬,,,,,,,310-0913,茨城県水戸市見川町2131番地952 メゾン見川103号,茨城県水戸市見川町2131番地952,赤塚駅,車,,,,,090-6115-0195,,,,090-6115-0195,,,,,,,,,41366,36.3419,140.4467
app.R CHANGED
@@ -1,58 +1,488 @@
 
 
 
1
  library(shiny)
2
- library(bslib)
3
  library(dplyr)
4
- library(ggplot2)
5
-
6
- df <- readr::read_csv("penguins.csv")
7
- # Find subset of columns that are suitable for scatter plot
8
- df_num <- df |> select(where(is.numeric), -Year)
9
-
10
- ui <- page_sidebar(
11
- theme = bs_theme(bootswatch = "minty"),
12
- title = "Penguins explorer",
13
- sidebar = sidebar(
14
- varSelectInput("xvar", "X variable", df_num, selected = "Bill Length (mm)"),
15
- varSelectInput("yvar", "Y variable", df_num, selected = "Bill Depth (mm)"),
16
- checkboxGroupInput("species", "Filter by species",
17
- choices = unique(df$Species), selected = unique(df$Species)
18
- ),
19
- hr(), # Add a horizontal rule
20
- checkboxInput("by_species", "Show species", TRUE),
21
- checkboxInput("show_margins", "Show marginal plots", TRUE),
22
- checkboxInput("smooth", "Add smoother"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  ),
24
- plotOutput("scatter")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  )
26
 
 
 
 
27
  server <- function(input, output, session) {
28
- subsetted <- reactive({
29
- req(input$species)
30
- df |> filter(Species %in% input$species)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  })
32
-
33
- output$scatter <- renderPlot(
34
- {
35
- p <- ggplot(subsetted(), aes(!!input$xvar, !!input$yvar)) +
36
- theme_light() +
37
- list(
38
- theme(legend.position = "bottom"),
39
- if (input$by_species) aes(color = Species),
40
- geom_point(),
41
- if (input$smooth) geom_smooth()
 
 
 
 
 
 
 
 
42
  )
43
-
44
- if (input$show_margins) {
45
- margin_type <- if (input$by_species) "density" else "histogram"
46
- p <- p |> ggExtra::ggMarginal(
47
- type = margin_type, margins = "both",
48
- size = 8, groupColour = input$by_species, groupFill = input$by_species
 
 
 
 
 
 
 
49
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
-
52
- p
53
- },
54
- res = 100
55
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
 
58
  shinyApp(ui, server)
 
1
+ # app.R - 警備マッチング可視化アプリ(改良版)
2
+ # 要件: 充足率表示、日付期間選択、要営業強化エリア識別
3
+
4
  library(shiny)
 
5
  library(dplyr)
6
+ library(leaflet)
7
+
8
+ # =========================================================
9
+ # 0) 設定
10
+ # =========================================================
11
+ BBOX <- list(
12
+ lat_min = 36.0,
13
+ lat_max = 36.9,
14
+ lng_min = 139.3,
15
+ lng_max = 140.3
16
+ )
17
+
18
+ # 充足率の閾値
19
+ THRESHOLD_LOW <- 80 # 80%未満 = 要営業強化(赤)
20
+ THRESHOLD_HIGH <- 100 # 100%以上 = 充足(緑)
21
+
22
+ # =========================================================
23
+ # 1) ユーティリティ
24
+ # =========================================================
25
+ read_csv_bom <- function(path) {
26
+ if (!file.exists(path)) stop(paste("ファイルが見つからない:", path))
27
+ df <- tryCatch(
28
+ read.csv(path, fileEncoding = "UTF-8-BOM", stringsAsFactors = FALSE, check.names = FALSE),
29
+ error = function(e) read.csv(path, stringsAsFactors = FALSE, check.names = FALSE)
30
+ )
31
+ df
32
+ }
33
+
34
+ to_date <- function(x) {
35
+ if (inherits(x, "Date")) return(x)
36
+ x <- as.character(x)
37
+ x <- trimws(x)
38
+ x[x == ""] <- NA
39
+ x2 <- gsub("/", "-", x, fixed = TRUE)
40
+ as.Date(x2)
41
+ }
42
+
43
+ haversine_km <- function(lat1, lon1, lat2, lon2) {
44
+ r <- 6371.0
45
+ to_rad <- function(x) x * pi / 180
46
+ dlat <- to_rad(lat2 - lat1)
47
+ dlon <- to_rad(lon2 - lon1)
48
+ a <- sin(dlat/2)^2 + cos(to_rad(lat1)) * cos(to_rad(lat2)) * sin(dlon/2)^2
49
+ 2 * r * asin(pmin(1, sqrt(a)))
50
+ }
51
+
52
+ extract_city <- function(addr) {
53
+ if (is.na(addr) || trimws(addr) == "") return(NA_character_)
54
+ a <- gsub(" ", " ", addr, fixed = TRUE)
55
+ a <- gsub("\\(.*?\\)", "", a)
56
+ a <- gsub("\\(.*?\\)", "", a)
57
+ a2 <- sub(".*県", "", a)
58
+ m <- regexpr("(市|町|村|区)", a2)
59
+ if (m[1] == -1) return(NA_character_)
60
+ endpos <- m[1] + attr(m, "match.length") - 1
61
+ substr(a2, 1, endpos)
62
+ }
63
+
64
+ # 充足率に応じた色を返す
65
+ get_fill_color <- function(rate) {
66
+ case_when(
67
+ is.na(rate) ~ "gray",
68
+ rate < THRESHOLD_LOW ~ "#e74c3c", # 赤 - 要営業強化
69
+ rate < THRESHOLD_HIGH ~ "#f39c12", # オレンジ - 注意
70
+ TRUE ~ "#27ae60" # 緑 - 充足
71
+ )
72
+ }
73
+
74
+ # =========================================================
75
+ # 2) データ読み込み&前処理
76
+ # =========================================================
77
+ load_all_data <- function() {
78
+ # ファイル名を新しいデータに変更
79
+ contract_raw <- read_csv_bom("ac_contract_list_geocoded.csv")
80
+ guard_raw <- read_csv_bom("ac_guard_master_geocoded.csv")
81
+ avail_raw <- read_csv_bom("ac_availability.csv")
82
+
83
+ # ---- contract_list ----
84
+ contract <- contract_raw %>%
85
+ mutate(
86
+ `案件予定日(開始)` = to_date(`案件予定日(開始)`),
87
+ `案件予定日(終了)` = to_date(`案件予定日(終了)`),
88
+ 現場住所 = paste0(
89
+ ifelse(is.na(`現場住所1`), "", `現場住所1`),
90
+ ifelse(is.na(`現場住所2`) | trimws(`現場住所2`) == "", "", paste0(" ", `現場住所2`))
91
+ ),
92
+ required_guards = `必要人数`,
93
+ site_city = `市区町村`
94
+ )
95
+
96
+ # ---- guard_master ----
97
+ # 「従業員番号」の代わりに「ユーザー番号」を使用
98
+ guard <- guard_raw %>%
99
+ mutate(
100
+ ユーザー番号 = suppressWarnings(as.integer(`ユーザー番号`)),
101
+ guard_city = vapply(`住所`, extract_city, character(1))
102
+ )
103
+
104
+ # ---- availability ----
105
+ # 「従業員番号」の代わりに「ユーザー番号」を使用
106
+ avail <- avail_raw %>%
107
+ mutate(
108
+ 日付 = to_date(`日付`),
109
+ ユーザー番号 = suppressWarnings(as.integer(`ユーザー番号`)),
110
+ available_flag = as.integer(`対応可否`)
111
+ )
112
+
113
+ list(contract = contract, guard = guard, avail = avail)
114
+ }
115
+
116
+ DATA <- NULL
117
+ LOAD_ERROR <- NULL
118
+ tryCatch({
119
+ DATA <- load_all_data()
120
+ }, error = function(e) {
121
+ LOAD_ERROR <<- e$message
122
+ })
123
+
124
+ # =========================================================
125
+ # 3) UI
126
+ # =========================================================
127
+ ui <- fluidPage(
128
+ tags$head(
129
+ tags$link(rel = "icon", href = "data:,"),
130
+ tags$style(HTML("
131
+ .legend-box { padding: 10px; background: white; border-radius: 5px; }
132
+ .legend-item { display: flex; align-items: center; margin: 5px 0; }
133
+ .legend-color { width: 20px; height: 20px; border-radius: 50%; margin-right: 8px; }
134
+ .summary-header { background-color: #f8f9fa; padding: 10px; border-radius: 5px; margin-bottom: 10px; }
135
+ "))
136
  ),
137
+ titlePanel("警備マッチング可視化(充足率・期間選択対応)"),
138
+ sidebarLayout(
139
+ sidebarPanel(
140
+ if (!is.null(LOAD_ERROR)) {
141
+ tags$div(
142
+ style = "color:#b00020; font-weight:600;",
143
+ paste0("データ読込エラー: ", LOAD_ERROR),
144
+ tags$br(),
145
+ "同じフォルダに ac_contract_list_geocoded.csv / ac_guard_master_geocoded.csv / ac_availability.csv を置いているか確認する。"
146
+ )
147
+ } else {
148
+ tagList(
149
+ h4("📅 期間選択"),
150
+ dateRangeInput(
151
+ "date_range",
152
+ "対象期間",
153
+ start = min(DATA$contract$`案件予定日(開始)`, na.rm = TRUE),
154
+ end = min(DATA$contract$`案件予定日(開始)`, na.rm = TRUE) + 7,
155
+ min = min(DATA$contract$`案件予定日(開始)`, na.rm = TRUE),
156
+ max = max(DATA$contract$`案件予定日(終了)`, na.rm = TRUE),
157
+ format = "yyyy/mm/dd",
158
+ language = "ja",
159
+ separator = " ~ "
160
+ ),
161
+ hr(),
162
+ h4("🗺️ 表示設定"),
163
+ checkboxInput("show_guards", "アベイラブル隊員を表示", TRUE),
164
+ radioButtons(
165
+ "match_mode",
166
+ "マッチング方法",
167
+ choices = c("市区町村一致" = "city", "距離(半径km)" = "dist"),
168
+ selected = "city"
169
+ ),
170
+ conditionalPanel(
171
+ condition = "input.match_mode == 'dist'",
172
+ numericInput("radius_km", "半径(km)", value = 20, min = 1, max = 200, step = 1)
173
+ ),
174
+ hr(),
175
+ h4("📊 凡例"),
176
+ tags$div(
177
+ class = "legend-box",
178
+ tags$div(class = "legend-item",
179
+ tags$div(class = "legend-color", style = "background-color: #27ae60;"),
180
+ tags$span("充足(100%以上)")
181
+ ),
182
+ tags$div(class = "legend-item",
183
+ tags$div(class = "legend-color", style = "background-color: #f39c12;"),
184
+ tags$span("注意(80-99%)")
185
+ ),
186
+ tags$div(class = "legend-item",
187
+ tags$div(class = "legend-color", style = "background-color: #e74c3c;"),
188
+ tags$span("要営業強化(80%未満)")
189
+ ),
190
+ tags$div(class = "legend-item",
191
+ tags$div(class = "legend-color", style = "background-color: #3498db; opacity: 0.7;"),
192
+ tags$span("アベイラブル隊員")
193
+ )
194
+ )
195
+ )
196
+ },
197
+ width = 3
198
+ ),
199
+ mainPanel(
200
+ # サマリー統計
201
+ fluidRow(
202
+ column(3,
203
+ tags$div(class = "summary-header",
204
+ h5("稼働現場数"),
205
+ textOutput("stat_sites", inline = TRUE)
206
+ )
207
+ ),
208
+ column(3,
209
+ tags$div(class = "summary-header",
210
+ h5("必要人数合計"),
211
+ textOutput("stat_required", inline = TRUE)
212
+ )
213
+ ),
214
+ column(3,
215
+ tags$div(class = "summary-header",
216
+ h5("対応可能人数"),
217
+ textOutput("stat_available", inline = TRUE)
218
+ )
219
+ ),
220
+ column(3,
221
+ tags$div(class = "summary-header",
222
+ h5("平均充足率"),
223
+ textOutput("stat_avg_rate", inline = TRUE)
224
+ )
225
+ )
226
+ ),
227
+ leafletOutput("map", height = 480),
228
+ br(),
229
+ h4("現場別 需給状況(選択期間)"),
230
+ tableOutput("summary"),
231
+ width = 9
232
+ )
233
+ )
234
  )
235
 
236
+ # =========================================================
237
+ # 4) Server
238
+ # =========================================================
239
  server <- function(input, output, session) {
240
+ if (!is.null(LOAD_ERROR)) {
241
+ output$map <- renderLeaflet({ leaflet() %>% addTiles() })
242
+ output$summary <- renderTable({
243
+ data.frame(エラー = LOAD_ERROR, stringsAsFactors = FALSE)
244
+ })
245
+ return()
246
+ }
247
+
248
+ contract <- DATA$contract
249
+ guard <- DATA$guard
250
+ avail <- DATA$avail
251
+
252
+ # 選択期間のデータを取得
253
+ daily <- reactive({
254
+ date_range <- input$date_range
255
+ d_start <- date_range[1]
256
+ d_end <- date_range[2]
257
+
258
+ # 期間内に稼働中の現場
259
+ active_sites <- contract %>%
260
+ filter(!is.na(`案件予定日(開始)`), !is.na(`案件予定日(終了)`)) %>%
261
+ filter(`案件予定日(開始)` <= d_end, `案件予定日(終了)` >= d_start)
262
+
263
+ # 期間内で「対応可」の日が1日でもある隊員
264
+ # 「従業員番号」→「ユーザー番号」に変更
265
+ available_emp <- avail %>%
266
+ filter(!is.na(日付), 日付 >= d_start, 日付 <= d_end, available_flag == 1L) %>%
267
+ distinct(ユーザー番号)
268
+
269
+ available_guards <- guard %>%
270
+ inner_join(available_emp, by = "ユーザー番号")
271
+
272
+ list(
273
+ date_start = d_start,
274
+ date_end = d_end,
275
+ active_sites = active_sites,
276
+ available_guards = available_guards
277
+ )
278
  })
279
+
280
+ # 需給サマリー計算
281
+ summary_tbl <- reactive({
282
+ dd <- daily()
283
+ sites <- dd$active_sites
284
+ gds <- dd$available_guards
285
+
286
+ if (nrow(sites) == 0) {
287
+ return(data.frame(メッセージ = "選択期間に稼働中の現場がない", stringsAsFactors = FALSE))
288
+ }
289
+
290
+ if (input$match_mode == "city") {
291
+ # gdsが空の場合は空のデータフレームを作成(型を明示)
292
+ if (nrow(gds) == 0) {
293
+ g_by_city <- data.frame(
294
+ guard_city = character(0),
295
+ available_guards = integer(0),
296
+ stringsAsFactors = FALSE
297
  )
298
+ } else {
299
+ g_by_city <- gds %>%
300
+ mutate(guard_city = as.character(ifelse(is.na(guard_city), "不明", guard_city))) %>%
301
+ count(guard_city, name = "available_guards")
302
+ }
303
+
304
+ result <- sites %>%
305
+ mutate(site_city = as.character(ifelse(is.na(site_city), "不明", site_city))) %>%
306
+ left_join(g_by_city, by = c("site_city" = "guard_city")) %>%
307
+ mutate(
308
+ available_guards = ifelse(is.na(available_guards), 0L, available_guards),
309
+ shortage = pmax(required_guards - available_guards, 0L),
310
+ fulfillment_rate = round(available_guards / required_guards * 100, 0)
311
  )
312
+ } else {
313
+ radius <- input$radius_km
314
+ if (is.null(radius) || is.na(radius) || radius <= 0) radius <- 20
315
+
316
+ if (nrow(gds) == 0) {
317
+ result <- sites %>%
318
+ mutate(
319
+ available_guards = 0L,
320
+ shortage = required_guards,
321
+ fulfillment_rate = 0
322
+ )
323
+ } else {
324
+ result <- sites %>%
325
+ rowwise() %>%
326
+ mutate(
327
+ available_guards = {
328
+ dist <- haversine_km(site_lat, site_lng, gds$home_lat, gds$home_lng)
329
+ sum(dist <= radius, na.rm = TRUE)
330
+ }
331
+ ) %>%
332
+ ungroup() %>%
333
+ mutate(
334
+ shortage = pmax(required_guards - available_guards, 0L),
335
+ fulfillment_rate = round(available_guards / required_guards * 100, 0)
336
+ )
337
  }
338
+ }
339
+
340
+ # 色と状態を追加
341
+ result <- result %>%
342
+ mutate(
343
+ fill_color = get_fill_color(fulfillment_rate),
344
+ status = case_when(
345
+ fulfillment_rate < THRESHOLD_LOW ~ "⚠️ 要営業強化",
346
+ fulfillment_rate < THRESHOLD_HIGH ~ "△ 注意",
347
+ TRUE ~ "○ 充足"
348
+ )
349
+ )
350
+
351
+ result
352
+ })
353
+
354
+ # 表示用テーブル
355
+ output$summary <- renderTable({
356
+ tbl <- summary_tbl()
357
+ if ("メッセージ" %in% colnames(tbl)) return(tbl)
358
+
359
+ tbl %>%
360
+ transmute(
361
+ 契約ID = contract_id,
362
+ 契約No = `契約No`,
363
+ 顧客 = `顧客`,
364
+ 件名 = paste0(`件名1`, ifelse(is.na(`件名2`) | trimws(`件名2`) == "", "", paste0(" ", `件名2`))),
365
+ 市区町村 = site_city,
366
+ 必要人数 = required_guards,
367
+ 対応可能 = as.integer(available_guards),
368
+ 充足率 = paste0(fulfillment_rate, "%"),
369
+ 状態 = status
370
+ )
371
+ })
372
+
373
+ # サマリー統計
374
+ output$stat_sites <- renderText({
375
+ dd <- daily()
376
+ paste0(nrow(dd$active_sites), " 件")
377
+ })
378
+
379
+ output$stat_required <- renderText({
380
+ tbl <- summary_tbl()
381
+ if ("メッセージ" %in% colnames(tbl)) return("-")
382
+ paste0(sum(tbl$required_guards, na.rm = TRUE), " 人")
383
+ })
384
+
385
+ output$stat_available <- renderText({
386
+ dd <- daily()
387
+ paste0(nrow(dd$available_guards), " 人")
388
+ })
389
+
390
+ output$stat_avg_rate <- renderText({
391
+ tbl <- summary_tbl()
392
+ if ("メッセージ" %in% colnames(tbl)) return("-")
393
+ avg_rate <- mean(tbl$fulfillment_rate, na.rm = TRUE)
394
+ paste0(round(avg_rate, 0), "%")
395
+ })
396
+
397
+ # 地図(初回のみ)
398
+ output$map <- renderLeaflet({
399
+ center_lat <- mean(c(BBOX$lat_min, BBOX$lat_max))
400
+ center_lng <- mean(c(BBOX$lng_min, BBOX$lng_max))
401
+
402
+ leaflet() %>%
403
+ addTiles() %>%
404
+ setView(lng = center_lng, lat = center_lat, zoom = 9) %>%
405
+ addLayersControl(
406
+ overlayGroups = c("現場(充足率)", "アベイラブル隊員"),
407
+ options = layersControlOptions(collapsed = FALSE)
408
+ )
409
+ })
410
+
411
+ # 地図更新(マーカー)
412
+ observe({
413
+ dd <- daily()
414
+ sites_data <- summary_tbl()
415
+ gds <- dd$available_guards
416
+
417
+ proxy <- leafletProxy("map")
418
+ proxy %>%
419
+ clearGroup("現場(充足率)") %>%
420
+ clearGroup("アベイラブル隊員")
421
+
422
+ # 現場マーカー(充足率付き)
423
+ if (!("メッセージ" %in% colnames(sites_data)) && nrow(sites_data) > 0) {
424
+ # CircleMarkersを追加
425
+ proxy %>%
426
+ addCircleMarkers(
427
+ data = sites_data,
428
+ lng = ~site_lng, lat = ~site_lat,
429
+ radius = 14,
430
+ color = ~fill_color,
431
+ fillColor = ~fill_color,
432
+ fillOpacity = 0.85,
433
+ weight = 2,
434
+ label = ~paste0(
435
+ "【", `契約No`, "】", `件名1`,
436
+ " | 充足率: ", fulfillment_rate, "%",
437
+ " | 必要: ", required_guards, "人",
438
+ " | 対応可: ", available_guards, "人"
439
+ ),
440
+ group = "現場(充足率)"
441
+ )
442
+
443
+ # 充足率ラベルを個別に追加(色を動的に設定するため)
444
+ for (i in seq_len(nrow(sites_data))) {
445
+ row <- sites_data[i, ]
446
+ proxy %>%
447
+ addLabelOnlyMarkers(
448
+ lng = row$site_lng,
449
+ lat = row$site_lat,
450
+ label = paste0(row$fulfillment_rate, "%"),
451
+ labelOptions = labelOptions(
452
+ noHide = TRUE,
453
+ direction = "top",
454
+ textOnly = TRUE,
455
+ style = list(
456
+ "font-weight" = "bold",
457
+ "font-size" = "11px",
458
+ "color" = "white",
459
+ "background-color" = row$fill_color,
460
+ "padding" = "2px 5px",
461
+ "border-radius" = "4px"
462
+ )
463
+ ),
464
+ group = "現場(充足率)"
465
+ )
466
+ }
467
+ }
468
+
469
+ # アベイラブル隊員マーカー
470
+ # 「従業員番号」→「ユーザー番号」に変更
471
+ if (isTRUE(input$show_guards) && nrow(gds) > 0) {
472
+ proxy %>%
473
+ addCircleMarkers(
474
+ data = gds,
475
+ lng = ~home_lng, lat = ~home_lat,
476
+ radius = 6,
477
+ color = "#3498db",
478
+ fillColor = "#3498db",
479
+ fillOpacity = 0.6,
480
+ weight = 1,
481
+ label = ~paste0("ユーザー番号: ", ユーザー番号, " | ", 苗字, " ", 名前, " | ", guard_city),
482
+ group = "アベイラブル隊員"
483
+ )
484
+ }
485
+ })
486
  }
487
 
488
  shinyApp(ui, server)