sugitora commited on
Commit
f2eeea4
·
verified ·
1 Parent(s): ff57627

Upload 5 files

Browse files
Dockerfile CHANGED
@@ -11,8 +11,8 @@ RUN R -e "library(shiny); library(dplyr); library(leaflet); cat('All packages OK
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
 
11
  # アプリディレクトリ
12
  WORKDIR /app
13
 
14
+ # ファイルをコピー(日付展開済みデータファイルに対応)
15
+ COPY app.R ac_date_contract_list.csv ac_date_guard_master.csv ac_date_availability.csv /app/
16
 
17
  # ポート設定
18
  EXPOSE 7860
ac_date_availability.csv ADDED
The diff for this file is too large to render. See raw diff
 
ac_date_contract_list.csv ADDED
The diff for this file is too large to render. See raw diff
 
ac_date_guard_master.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,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0152,栃木県宇都宮市西川田6-4-18,NA,西川田,車,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,42761,36.507534,139.8582
3
+ 391,u00033,u00033,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0974,栃木県宇都宮市竹林町123 クレセントレジデンスC202,秋田県大館市釈迦内字山神台1-2,駅東公園前,車,NA,NA,NA,NA,028-627-6584,NA,NA,NA,028-627-6584,NA,NA,NA,NA,NA,NA,NA,NA,43498,36.578796,139.91333
4
+ 397,u00039,u00039,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,322-0045,栃木県鹿沼市上殿町373-1,栃木県鹿沼市上殿町373-1,新鹿沼,車,NA,NA,NA,NA,090-2245-5253,NA,NA,NA,090-2245-5253,NA,NA,NA,NA,NA,NA,NA,NA,43655,36.548542,139.750244
5
+ 401,u00043,u00043,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0139,栃木県宇都宮市若松原2-18-9,NA,雀宮,車,NA,NA,NA,NA,080-6548-1226,NA,NA,NA,080-6548-1226,NA,NA,NA,NA,NA,NA,NA,NA,43783,36.498676,139.869049
6
+ 412,u00054,u00054,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,324-0031,栃木県大田原市藤沢363,NA,片岡,車,NA,NA,NA,NA,080-1683-8271,NA,NA,NA,080-1683-8271,NA,NA,NA,NA,NA,NA,NA,NA,44096,36.786404,140.029556
7
+ 422,u00064,u00064,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0952,栃木県宇都宮市泉が丘6-2-17  アザレヤマンション206,栃木県宇都宮市泉が丘6-2-17  アザレヤマンション206,峰,車,NA,NA,NA,NA,090-9675-7861,NA,NA,NA,090-9675-7861,NA,NA,NA,NA,NA,NA,NA,NA,44324,36.569054,139.917953
8
+ 423,u00065,u00065,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0952,栃木県宇都宮市泉が丘6-2-17  アザレアマンション206,栃木県宇都宮市泉が丘6-2-17  アザレアマンション206,峰,車,NA,NA,NA,NA,095-844-6043,NA,NA,NA,095-844-6043,NA,NA,NA,NA,NA,NA,NA,NA,44324,36.569054,139.917953
9
+ 440,u00082,u00082,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,329-1233,栃木県塩谷郡高根沢町宝積寺2248-32,NA,宝積寺,車,NA,NA,NA,NA,028-675-2766,NA,NA,NA,028-675-2766,NA,NA,NA,NA,NA,NA,NA,NA,44629,36.624477,139.985428
10
+ 447,u00089,u00089,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,322-0036,栃木県鹿沼市下田町2-1403-16,栃木県鹿沼市下田町2-1403-16,新鹿沼,車,NA,NA,NA,NA,0289-62-3256,NA,NA,NA,0289-62-3256,NA,NA,NA,NA,NA,NA,NA,NA,44819,36.562962,139.748825
11
+ 449,U00091,u00091,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0111,栃木県宇都宮市川田町1261-3 沢村ハイツ101,NA,南宇都宮,車,NA,NA,NA,NA,090-8814-0030,NA,NA,NA,090-8814-0030,NA,NA,NA,NA,NA,NA,NA,NA,44887,36.528797,139.883102
12
+ 450,u00092,u00092,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-3426,栃木県芳賀郡市貝町赤羽418-27,NA,多田羅,車,NA,NA,NA,NA,090-2620-7084,NA,NA,NA,090-2620-7084,NA,NA,NA,NA,NA,NA,NA,NA,45026,36.539886,140.064819
13
+ 451,u00093,u00093,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0982,栃木県宇都宮市御幸ケ原町143-19 サンビレッジ御幸ヶ原A203,NA,峰,車,NA,NA,NA,NA,080-2305-7654,NA,NA,NA,080-2305-7654,NA,NA,NA,NA,NA,NA,NA,NA,45178,36.583855,139.918854
14
+ 1022,u00108,k000162,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0932,栃木県宇都宮市平松本町364 県住541,NA,駅東公園前,車,NA,NA,NA,NA,080-6111-5952,NA,NA,NA,080-6111-5952,NA,NA,NA,NA,NA,NA,NA,NA,45541,36.544983,139.910461
15
+ 1050,u00109,k000190,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0925,栃木県宇都宮市東簗瀬1丁目42番地4 レクエルドユーミー301,埼玉県秩父市上影森31-1,宇都宮,車,NA,NA,NA,NA,0494-24-5432,NA,NA,NA,0494-24-5432,NA,NA,NA,NA,NA,NA,NA,NA,45545,36.538403,139.90274
16
+ 1147,u00114,k000267,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0236,栃木県下都賀郡壬生町上稲葉1976-2,NA,東武金崎,車,NA,NA,NA,NA,080-6757-6348,NA,NA,NA,080-6757-6348,NA,NA,NA,NA,NA,NA,NA,NA,45591,36.451187,139.772858
17
+ 1148,u00115,k000268,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-4337,栃木県真岡市上高間木1-7-2 スカイヒルズC-102,NA,真岡駅,車,NA,NA,NA,NA,090-5337-9153,NA,NA,NA,090-5337-9153,NA,NA,NA,NA,NA,NA,NA,NA,45474,36.445232,139.99028
18
+ 1241,u00116,k000361,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,329-1104,栃木県宇都宮市下岡本町1949番地5,栃木県宇都宮市下岡本町1949番地5,岡本駅,車,NA,NA,NA,NA,090-4535-8389,45682,NA,NA,090-4535-8389,NA,NA,NA,NA,NA,NA,NA,NA,45600,36.59687,139.94136
19
+ 1350,u00061,k000458,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,322-0031,栃木県鹿沼市睦町320睦町市営住宅3-5,栃木県鹿沼市茂呂1858番地18,鹿沼,車,NA,NA,NA,NA,090-2918-3572,NA,NA,NA,090-2918-3572,NA,NA,NA,NA,NA,NA,NA,NA,45772,36.57291,139.752823
20
+ 1353,E00406,k000461,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-3423,栃木県芳賀郡市貝町市塙1215-1,栃木県宇都宮市屋板町529番地1,市塙,車,NA,NA,NA,NA,090-9016-3608,NA,NA,NA,090-9016-3608,NA,NA,NA,NA,NA,NA,NA,NA,45785,36.548981,140.108917
21
+ 1415,E00413,k000523,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,322-0344,栃木県鹿沼市西沢町324番地,栃木県鹿沼市西沢町324番地,樅山,車,NA,NA,NA,NA,090-8894-0993,NA,NA,NA,090-8894-0993,NA,NA,NA,NA,NA,NA,NA,NA,45930,36.525009,139.697235
22
+ 1425,F00408,k000533,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0152,栃木県宇都宮市西川田5丁目27番13号 シャトルハイツA102,栃木県宇都宮市川田町884番地,西川田,車,NA,NA,NA,NA,090-6658-0525,NA,NA,NA,090-6658-0525,NA,NA,NA,NA,NA,NA,NA,NA,45916,36.511845,139.853455
23
+ 1488,F00411,k000568,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0932,栃木県宇都宮市平松本町364番地 県営平松本町住宅5棟41号,栃木県宇都宮市平松本町364番地1,駅東公園前,車,NA,NA,NA,NA,080-5984-9707,NA,NA,NA,080-5984-9707,NA,NA,NA,NA,NA,NA,NA,NA,45973,36.544983,139.910461
24
+ 476,E00113,e00113,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,307-0042,茨城県結城市江川新宿1988番地,NA,間々田,車,NA,NA,NA,NA,0296-35-2701,NA,NA,NA,0296-35-2701,NA,NA,NA,NA,NA,NA,NA,NA,38844,36.235897,139.829056
25
+ 479,E00347,e00347,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,329-4412,栃木県栃木市大平町北武井670番地,NA,栃木,車,NA,NA,NA,NA,080-1248-7855,NA,NA,NA,080-1248-7855,NA,NA,NA,NA,NA,NA,NA,NA,41699,36.357525,139.747116
26
+ 482,E00384,e00384,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,328-0075,栃木県栃木市箱森町11-11,NA,栃木,車,NA,NA,NA,NA,0282-24-6701,NA,NA,NA,0282-24-6701,NA,NA,NA,NA,NA,NA,NA,NA,44512,36.386356,139.716568
27
+ 487,E00391,e00391,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,307-0037,茨城県結城市東茂呂1639,NA,間々田,車,NA,NA,NA,NA,0296-48-0621,NA,NA,NA,0296-48-0621,NA,NA,NA,NA,NA,NA,NA,NA,45204,36.217041,139.84848
28
+ 488,F00349,f00349,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,323-0829,栃木県小山市東城南3丁目4番地2,NA,小山,車,NA,NA,NA,NA,080-1041-6718,NA,NA,NA,080-1041-6718,NA,NA,NA,NA,NA,NA,NA,NA,42010,36.293842,139.81572
29
+ 494,F00400,f00400,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,327-0004,栃木県佐野市赤坂町200-6 レジデンス赤坂B棟,NA,佐野駅,電車,NA,NA,NA,NA,090-9011-4893,NA,NA,NA,090-9011-4893,NA,NA,NA,NA,NA,NA,NA,NA,45204,36.306011,139.570923
30
+ 506,E00349,e00349,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,329-0205,栃木県小山市間々田871番地2,NA,間々田,電車,NA,NA,NA,NA,080-3540-4550,NA,NA,NA,080-3540-4550,NA,NA,NA,NA,NA,NA,NA,NA,41706,36.269428,139.769562
31
+ 509,F00306,f00306,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,328-0054,栃木県栃木市平井町88番地7,NA,栃木,電車,NA,NA,NA,NA,090-3576-7883,NA,NA,NA,090-3576-7883,NA,NA,NA,NA,NA,NA,NA,NA,40579,36.372543,139.710281
32
+ 510,F00326,f00326,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,307-0001,茨城県結城市大木2377番地1,NA,小田林,車,NA,NA,NA,NA,0296-35-1180,NA,NA,NA,0296-35-1180,NA,NA,NA,NA,NA,NA,NA,NA,41343,36.260334,139.847702
33
+ 1156,F00407,k000276,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,323-0826,栃木県小山市雨ケ谷827番地3,NA,小山駅,車,NA,NA,NA,NA,090-1552-0266,45604,NA,NA,090-1552-0266,NA,NA,NA,NA,NA,NA,NA,NA,45598,36.284828,139.819977
34
+ 1447,E00416,k000555,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,329-4304,栃木県栃木市岩舟町静和306番地1,栃木県栃木市岩舟町静和856番地1,静和,車,NA,NA,NA,NA,090-4598-3000,NA,NA,NA,090-4598-3000,NA,NA,NA,NA,NA,NA,NA,NA,45959,36.328819,139.686264
35
+ 1454,E00417,k000562,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,323-0818,栃木県小山市大字塚崎1389番地,栃木県小山市大字塚崎1389番地,間々田,車,NA,NA,NA,NA,070-3666-5345,NA,NA,NA,070-3666-5345,NA,NA,NA,NA,NA,NA,NA,NA,45966,36.272442,139.806366
36
+ 478,E00342,e00342,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,324-0012,栃木県大田原市南金丸381番地2,NA,那須塩原,車,NA,NA,NA,NA,080-1347-5090,NA,NA,NA,080-1347-5090,NA,NA,NA,NA,NA,NA,NA,NA,41529,36.857639,140.093979
37
+ 480,E00352,e00352,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,329-1311,栃木県さくら市氏家1806-8,NA,氏家,車,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,41825,36.67675,139.967819
38
+ 483,E00385,e00385,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,371-0015,群馬県前橋市三河町2-4-1 ライオンズマンション前橋316号,NA,前橋,電車,NA,NA,NA,NA,027-288-2687,NA,NA,NA,027-288-2687,NA,NA,NA,NA,NA,NA,NA,NA,44384,36.384705,139.079025
39
+ 490,F00386,f00386,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,366-0002,埼玉県深谷市下手計1059番地 コスモリヴェール3-B号,NA,深谷,電車,NA,NA,NA,NA,080-4141-0426,NA,NA,NA,080-4141-0426,NA,NA,NA,NA,NA,NA,NA,NA,44354,36.232761,139.270966
40
+ 491,F00390,f00390,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,320-0056,栃木県宇都宮市戸祭3-8-17 グリーンプラザ202,NA,東武宇都宮,車,NA,NA,NA,NA,090-4941-5349,NA,NA,NA,090-4941-5349,NA,NA,NA,NA,NA,NA,NA,NA,44798,36.574226,139.86644
41
+ 496,F00402,f00402,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0844,群馬県高崎市和田多中町13-19,NA,南高崎,徒歩,NA,NA,NA,NA,027-325-3623,NA,NA,NA,027-325-3623,NA,NA,NA,NA,NA,NA,NA,NA,45331,36.311798,139.015732
42
+ 497,M00017,m00017,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0852,群馬県高崎市中居町2丁目22番地1 県住F棟151号,NA,倉賀野,車,NA,NA,NA,NA,027-253-4464,NA,NA,NA,027-253-4464,NA,NA,NA,NA,NA,NA,NA,NA,40088,36.313919,139.044968
43
+ 498,M00021,m00021,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0004,群馬県高崎市井野町16番地4 吉田アパート104号,NA,井野(群馬県),車,NA,NA,NA,NA,0273-64-3485,NA,NA,NA,0273-64-3485,NA,NA,NA,NA,NA,NA,NA,NA,40138,36.360188,139.020721
44
+ 499,M00026,m00026,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,375-0014,群馬県藤岡市下栗須45番地13,NA,群馬藤岡,車,NA,NA,NA,NA,080-6625-1498,NA,NA,NA,080-6625-1498,NA,NA,NA,NA,NA,NA,NA,NA,40325,36.260288,139.092667
45
+ 500,M00056,m00056,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-3103,群馬県高崎市箕郷町下芝395番地3,NA,群馬八幡,車,NA,NA,NA,NA,090-2629-8848,NA,NA,NA,090-2629-8848,NA,NA,NA,NA,NA,NA,NA,NA,41913,36.37392,138.962112
46
+ 501,M00083,m00083,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,367-0055,埼玉県本庄市若泉2丁目7番10号,NA,本庄,電車,NA,NA,NA,NA,090-8586-6388,NA,NA,NA,090-8586-6388,NA,NA,NA,NA,NA,NA,NA,NA,43357,36.24818,139.184006
47
+ 502,M00087,m00087,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-1201,群馬県高崎市倉賀野町6387 エトワールナイン201号,NA,倉賀野,車,NA,NA,NA,NA,027-327-9065,NA,NA,NA,027-327-9065,NA,NA,NA,NA,NA,NA,NA,NA,43613,36.298168,139.057709
48
+ 503,E00355,e00355,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0132,栃木県宇都宮市雀の宮5丁目6番17号,NA,雀宮,車,NA,NA,NA,NA,028-655-3367,NA,NA,NA,028-655-3367,NA,NA,NA,NA,NA,NA,NA,NA,41890,36.489674,139.876083
49
+ 504,M00042,m00042,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0851,群馬県高崎市上中居町263番地1 ハーベスト上中居103,NA,高崎,徒歩,NA,NA,NA,NA,011-836-0353,NA,NA,NA,011-836-0353,NA,NA,NA,NA,NA,NA,NA,NA,41221,36.318947,139.030289
50
+ 505,E00191,e00191,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,963-1411,福島県郡山市湖南町舟津849,NA,上戸(福島県),車,NA,NA,NA,NA,090-9371-7612,NA,NA,NA,090-9371-7612,NA,NA,NA,NA,NA,NA,NA,NA,39284,37.404057,140.117752
51
+ 507,M00075,m00075,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-1111,群馬県佐波郡玉村町南玉1012番地6,NA,新町(群馬県),車,NA,NA,NA,NA,0270-64-0525,NA,NA,NA,0270-64-0525,NA,NA,NA,NA,NA,NA,NA,NA,42980,36.304165,139.137924
52
+ 508,M00076,m00076,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0046,群馬県高崎市江木町1142-1 ロイヤル88 2B,NA,高崎問屋町,徒歩,NA,NA,NA,NA,080-4129-3321,NA,NA,NA,080-4129-3321,NA,NA,NA,NA,NA,NA,NA,NA,43088,36.334232,139.02066
53
+ 511,F00356,f00356,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,320-0011,栃木県宇都宮市富士見が丘4-4-8 ニュー富士見マンション101,NA,宇都宮,車,NA,NA,NA,NA,080-3368-3845,NA,NA,NA,080-3368-3845,NA,NA,NA,NA,NA,NA,NA,NA,42567,36.587967,139.889954
54
+ 512,E00393,e00393,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,329-1104,栃木県宇都宮市下岡本町3766-9,NA,岡本(栃木県),車,NA,NA,NA,NA,080-5079-5634,NA,NA,NA,080-5079-5634,NA,NA,NA,NA,NA,NA,NA,NA,45371,36.598873,139.929016
55
+ 516,M00096,m00096,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0873,群馬県高崎市豊岡町1581,NA,北高崎,車,NA,NA,NA,NA,090-5430-1906,NA,NA,NA,090-5430-1906,NA,NA,NA,NA,NA,NA,NA,NA,45312,36.321964,139.003281
56
+ 1141,E00399,k000261,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,329-0618,栃木県河内郡上三川町しらさぎ1-23-8,NA,石橋(栃木県),車,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,45595,36.441288,139.909698
57
+ 1242,E00402,k000362,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0973,栃木県宇都宮市岩曽町807番地11,静岡県御殿場市川島田698番地4,宇都宮駅,車,NA,NA,NA,NA,090-2420-3087,45685,NA,NA,090-2420-3087,NA,NA,NA,NA,NA,NA,NA,NA,45682,36.587547,139.905899
58
+ 1252,E00403,k000372,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0816,群馬県高崎市常盤町127番地1 エトワール高崎常盤町402号,青森県つがる市木造筒木坂松本27番地,高崎駅,徒歩,NA,NA,NA,NA,046-281-2671,45704,NA,NA,046-281-2671,NA,NA,NA,NA,NA,NA,NA,NA,45700,36.329308,138.996719
59
+ 1273,E00404,k000393,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,379-0111,群馬県安中市板鼻618番地52,群馬県安中市板鼻618番地52,安中,車,NA,NA,NA,NA,090-2569-9618,45717,NA,NA,090-2569-9618,NA,NA,NA,NA,NA,NA,NA,NA,45700,36.345493,138.931396
60
+ 1328,E00405,k000436,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-4363,栃木県真岡市亀山104番地12,栃木県真岡市東大島1242番地2,真岡,車,NA,NA,NA,NA,090-2201-1335,45756,NA,NA,090-2201-1335,NA,NA,NA,NA,NA,NA,NA,NA,45744,36.454987,139.98877
61
+ 1494,E00419,k000574,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-1201,群馬県高崎市倉賀野町1815 シオン桜木201,群馬県高崎市倉賀野町1815番地1,倉賀野,電車,NA,NA,NA,NA,090-9208-9116,NA,NA,NA,090-9208-9116,NA,NA,NA,NA,NA,NA,NA,NA,45958,36.300446,139.05162
62
+ 979,W00003,k000119,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,379-2311,群馬県みどり市笠懸町阿左美484番地10,NA,阿左美,車,NA,NA,NA,NA,090-3474-5581,NA,NA,NA,090-3474-5581,NA,NA,NA,NA,NA,NA,NA,NA,45503,36.374332,139.30098
63
+ 1128,X00012,k000248,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-3501,群馬県北群馬郡榛東村長岡209,NA,八木原,車,NA,NA,NA,NA,090-8493-2106,NA,NA,NA,090-8493-2106,NA,NA,NA,NA,NA,NA,NA,NA,45556,36.445892,138.985641
64
+ 1138,X00013,k000258,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,373-0832,群馬県太田市富沢町172-6,NA,細谷(群馬県),車,NA,NA,NA,NA,0276-38-3754,NA,NA,NA,0276-38-3754,NA,NA,NA,NA,NA,NA,NA,NA,45563,36.261921,139.356247
65
+ 1167,W00007,k000287,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0511,群馬県邑楽郡大泉町北小泉1丁目8−14,群馬県邑楽郡大泉町北小泉1丁目8番,小泉町(群馬県),車,NA,NA,NA,NA,0276-61-0683,45607,NA,NA,0276-61-0683,NA,NA,NA,NA,NA,NA,NA,NA,45600,36.261673,139.421478
66
+ 1175,X00015,k000295,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0522,群馬県邑楽郡大泉町富士1丁目6番21号,群馬県邑楽郡大泉町1丁目1688番地27,西小泉,車,NA,NA,NA,NA,0276-63-6193,45615,NA,NA,0276-63-6193,NA,NA,NA,NA,NA,NA,NA,NA,45615,36.248318,139.415558
67
+ 1176,X00017,k000296,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,360-0831,埼玉県熊谷市久保島811番地1 熊谷玉井住宅B-612,埼玉県熊谷市久保島811番地1,籠原,車,NA,NA,NA,NA,070-1426-4750,45619,NA,NA,070-1426-4750,NA,NA,NA,NA,NA,NA,NA,NA,45619,36.168678,139.347275
68
+ 1282,W00009,k000402,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,379-2313,群馬県みどり市笠懸町鹿615番地19,群馬県みどり市笠懸町鹿615番地19,岩宿,車,NA,NA,NA,NA,090-3405-0272,NA,NA,NA,090-3405-0272,NA,NA,NA,NA,NA,NA,NA,NA,45720,36.383705,139.278595
69
+ 1367,X00018,k000475,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,326-0338,栃木県足利市福居町1511番地8,群馬県桐生市相生町2丁目518番地10,福居,車,NA,NA,NA,NA,080-3215-0091,NA,NA,NA,080-3215-0091,NA,NA,NA,NA,NA,NA,NA,NA,45839,36.307526,139.461578
70
+ 1388,E00408,k000496,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,326-0824,栃木県足利市八幡町600番地20 県営八幡住宅243,栃木県足利市若草町3番地3,野州山辺,車,NA,NA,NA,NA,080-125-17584,NA,NA,NA,080-125-17584,NA,NA,NA,NA,NA,NA,NA,NA,45887,36.326309,139.434509
71
+ 1397,E00410,k000505,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,377-0003,群馬県渋川市八木原1280番地2 油屋アパート1号室,群馬県渋川市北橘町真壁1634番地58,八木原,車,NA,NA,NA,NA,090-4412-7342,NA,NA,NA,090-4412-7342,NA,NA,NA,NA,NA,NA,NA,NA,45894,36.45789,139.016739
72
+ 1428,F00414,k000536,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,370-0883,群馬県高崎市剣崎町414番地10,群馬県高崎市剣崎町414番地10,群馬八幡,車,NA,NA,NA,NA,090-1100-3025,NA,NA,NA,090-1100-3025,NA,NA,NA,NA,NA,NA,NA,NA,45944,36.343983,138.952698
73
+ 392,u00034,u00034,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,320-0855,栃木県宇都宮市上欠町1231-342,栃木県宇都宮市上欠町1231-342,鶴田,車,NA,NA,NA,NA,028-648-1660,NA,NA,NA,028-648-1660,NA,NA,NA,NA,NA,NA,NA,NA,43517,36.553001,139.827805
74
+ 431,u00073,u00073,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,320-0075,栃木県宇都宮市宝木本町1148-31,NA,東武宇都宮,車,NA,NA,NA,NA,090-5767-9202,NA,NA,NA,090-5767-9202,NA,NA,NA,NA,NA,NA,NA,NA,44343,36.600761,139.852051
75
+ 454,u00096,u00096,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-3222,栃木県宇都宮市野高谷町515-2,栃木県さくら市下河戸770,ゆいの杜東,車,NA,NA,NA,NA,090-7329-1217,NA,NA,NA,090-7329-1217,NA,NA,NA,NA,NA,NA,NA,NA,45264,36.561592,139.997681
76
+ 492,F00398,f00398,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,323-0811,栃木県小山市犬塚3-26-20 ルミエールV102,NA,NA,NA,NA,NA,NA,NA,090-2022-5821,NA,NA,NA,090-2022-5821,NA,NA,NA,NA,NA,NA,NA,NA,45109,36.313801,139.833725
77
+ 493,F00399,f00399,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,306-0212,茨城県古河市久能1139-1,NA,NA,NA,NA,NA,NA,NA,090-5339-2813,NA,NA,NA,090-5339-2813,NA,NA,NA,NA,NA,NA,NA,NA,45159,36.163593,139.769791
78
+ 1018,k000158,k000158,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,326-0822,栃木県足利市田中町942-3 サクラ��ンション301,NA,足利市,車,NA,NA,NA,NA,080-5194-8108,NA,NA,NA,080-5194-8108,NA,NA,NA,NA,NA,NA,NA,NA,45519,36.32539,139.448761
79
+ 1020,X00010,k000160,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,326-0141,栃木県足利市小俣町382-3,NA,小俣(栃木県),車,NA,NA,NA,NA,090-1460-0858,NA,NA,NA,090-1460-0858,NA,NA,NA,NA,NA,NA,NA,NA,45519,36.371307,139.376205
80
+ 1177,X00016,k000297,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,326-0335,栃木県足利市上渋垂町119番地1,栃木県足利市福富町2013番地1,福居,車,NA,NA,NA,NA,090-5550-8568,45619,NA,NA,090-5550-8568,NA,NA,NA,NA,NA,NA,NA,NA,45619,36.301594,139.461411
81
+ 1225,E00401,k000345,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,323-0027,栃木県小山市花垣町1丁目6番29号,栃木県小山市花垣町1丁目6番,小山駅,車,NA,NA,NA,NA,080-6785-1219,45670,NA,NA,080-6785-1219,NA,NA,NA,NA,NA,NA,NA,NA,45311,36.322571,139.805649
82
+ 1358,E00407,k000466,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,3200075,栃木県宇都宮市宝木本町1246番地7 アムールアドニスⅡ 201,栃木県日光市土沢1810番地14,東武宇都宮,車,NA,NA,NA,NA,090-4923-8916,NA,NA,NA,090-4923-8916,NA,NA,NA,NA,NA,NA,NA,NA,45821,36.604252,139.848648
83
+ 1391,E00409,k000499,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,322-0526,栃木県鹿沼市楡木町661番地4,栃木県鹿沼市下奈良部町307番地,楡木,車,NA,NA,NA,NA,090-7191-7239,NA,NA,NA,090-7191-7239,NA,NA,NA,NA,NA,NA,NA,NA,45895,36.50853,139.747299
84
+ 1412,F00409,k000520,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,322-0026,栃木県鹿沼市茂呂1175−2 K.U.3A 102,韓国,鹿沼,車,NA,NA,NA,NA,070-5545-4903,NA,NA,NA,070-5545-4903,NA,NA,NA,NA,NA,NA,NA,NA,45922,36.548313,139.782623
85
+ 1432,E00415,k000540,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,307-0001,茨城県結城市大字結城10753番地6,茨城県結城市大字結城10753番地6,小田林,車,NA,NA,NA,NA,080-5505-8698,NA,NA,NA,080-5505-8698,NA,NA,NA,NA,NA,NA,NA,NA,45947,36.307152,139.851349
86
+ 1491,E00418,k000571,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,321-0904,栃木県宇都宮市陽東4-14-40 ひがしハイツワンA101,秋田県鹿角郡小坂町小坂字下前田35-6,陽東3丁目,車,NA,NA,NA,NA,090-4606-8700,NA,NA,NA,090-4606-8700,NA,NA,NA,NA,NA,NA,NA,NA,45978,36.558399,139.925934
87
+ 481,E00362,e00362,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,323-0014,栃木県小山市喜沢1148番地18,栃木県下野市1657番地24,小山,車,NA,NA,NA,NA,070-2797-1224,NA,NA,NA,070-2797-1224,NA,NA,NA,NA,NA,NA,NA,NA,42786,36.33815,139.81604
88
+ 486,E00389,e00389,NA,NA,NA,NA,栃木・群馬,NA,NA,NA,NA,NA,NA,320-0053,栃木県宇都宮市戸祭町3018-2 むぎくら第4ハイツB203号室,NA,NA,NA,NA,NA,NA,NA,090-4636-6540,NA,NA,NA,090-4636-6540,NA,NA,NA,NA,NA,NA,NA,NA,45054,36.575195,139.876343
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,5 +1,6 @@
1
- # app.R - 警備マッチング可視化アプリ(改良版)
2
  # 要件: 充足率表示、日付期間選択、要営業強化エリア識別
 
3
 
4
  library(shiny)
5
  library(dplyr)
@@ -31,11 +32,13 @@ read_csv_bom <- function(path) {
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
  }
@@ -75,26 +78,27 @@ get_fill_color <- function(rate) {
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(`ユーザー番号`)),
@@ -102,13 +106,18 @@ load_all_data <- function() {
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
  }
@@ -134,7 +143,7 @@ ui <- fluidPage(
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)) {
@@ -142,7 +151,7 @@ ui <- fluidPage(
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(
@@ -150,20 +159,20 @@ ui <- fluidPage(
150
  dateRangeInput(
151
  "date_range",
152
  "対象期間",
153
- start = as.Date("2024-04-01"),
154
- end = as.Date("2026-03-31"),
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
  ),
@@ -189,9 +198,11 @@ ui <- fluidPage(
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
@@ -201,7 +212,7 @@ ui <- fluidPage(
201
  fluidRow(
202
  column(3,
203
  tags$div(class = "summary-header",
204
- h5("稼働現場数"),
205
  textOutput("stat_sites", inline = TRUE)
206
  )
207
  ),
@@ -226,7 +237,7 @@ ui <- fluidPage(
226
  ),
227
  leafletOutput("map", height = 480),
228
  br(),
229
- h4("現場別 需給状況(選択期間)"),
230
  tableOutput("summary"),
231
  width = 9
232
  )
@@ -255,87 +266,54 @@ server <- function(input, output, session) {
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 %>%
@@ -351,29 +329,33 @@ server <- function(input, output, session) {
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({
@@ -383,8 +365,9 @@ server <- function(input, output, session) {
383
  })
384
 
385
  output$stat_available <- renderText({
386
- dd <- daily()
387
- paste0(nrow(dd$available_guards), "")
 
388
  })
389
 
390
  output$stat_avg_rate <- renderText({
@@ -403,7 +386,7 @@ server <- function(input, output, session) {
403
  addTiles() %>%
404
  setView(lng = center_lng, lat = center_lat, zoom = 9) %>%
405
  addLayersControl(
406
- overlayGroups = c("現場(充足率)", "アベイラブル隊員"),
407
  options = layersControlOptions(collapsed = FALSE)
408
  )
409
  })
@@ -412,78 +395,99 @@ server <- function(input, output, session) {
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)
489
-
 
1
+ # app.R - 警備マッチング可視化アプリ(日付×contract_idベースマッチング対応版)
2
  # 要件: 充足率表示、日付期間選択、要営業強化エリア識別
3
+ # 修正: ac_date_xxx.csv対応、日付とcontract_idの組み合わせでマッチング
4
 
5
  library(shiny)
6
  library(dplyr)
 
32
  df
33
  }
34
 
35
+ # 日付変換関数(yyyy/m/d または yyyy-m-d 形式対応)
36
  to_date <- function(x) {
37
  if (inherits(x, "Date")) return(x)
38
  x <- as.character(x)
39
  x <- trimws(x)
40
  x[x == ""] <- NA
41
+ # / を - に統一
42
  x2 <- gsub("/", "-", x, fixed = TRUE)
43
  as.Date(x2)
44
  }
 
78
  # 2) データ読み込み&前処理
79
  # =========================================================
80
  load_all_data <- function() {
81
+ # 新しいファイル名に変更
82
+ contract_raw <- read_csv_bom("ac_date_contract_list.csv")
83
+ guard_raw <- read_csv_bom("ac_date_guard_master.csv")
84
+ avail_raw <- read_csv_bom("ac_date_availability.csv")
85
 
86
+ # ---- contract_list (日付展開済み) ----
87
+ # 対応日は yyyy/m/d 形式の文字列 → Dateに変換
88
  contract <- contract_raw %>%
89
  mutate(
90
+ 対応日 = to_date(`対応日`),
 
91
  現場住所 = paste0(
92
  ifelse(is.na(`現場住所1`), "", `現場住所1`),
93
  ifelse(is.na(`現場住所2`) | trimws(`現場住所2`) == "", "", paste0(" ", `現場住所2`))
94
  ),
95
  required_guards = `必要人数`,
96
  site_city = `市区町村`
97
+ ) %>%
98
+ # 2025/1/1〜2025/12/31のデータに限定
99
+ filter(対応日 >= as.Date("2025-01-01"), 対応日 <= as.Date("2025-12-31"))
100
 
101
  # ---- guard_master ----
 
102
  guard <- guard_raw %>%
103
  mutate(
104
  ユーザー番号 = suppressWarnings(as.integer(`ユーザー番号`)),
 
106
  )
107
 
108
  # ---- availability ----
109
+ # 日付はyyyy/m/d形式
110
  avail <- avail_raw %>%
111
  mutate(
112
  日付 = to_date(`日付`),
113
  ユーザー番号 = suppressWarnings(as.integer(`ユーザー番号`)),
114
+ available_flag = as.integer(`対応可否`),
115
+ 担当予定contract_id = trimws(as.character(`担当予定contract_id`))
116
+ ) %>%
117
+ # 担当予定contract_idが空文字やNAの場合はNA扱い
118
+ mutate(担当予定contract_id = ifelse(担当予定contract_id == "" | 担当予定contract_id == "NA", NA_character_, 担当予定contract_id)) %>%
119
+ # 2025/1/1〜2025/12/31のデータに限定
120
+ filter(日付 >= as.Date("2025-01-01"), 日付 <= as.Date("2025-12-31"))
121
 
122
  list(contract = contract, guard = guard, avail = avail)
123
  }
 
143
  .summary-header { background-color: #f8f9fa; padding: 10px; border-radius: 5px; margin-bottom: 10px; }
144
  "))
145
  ),
146
+ titlePanel("警備マッチング可視化(日付×契約ID別対応)"),
147
  sidebarLayout(
148
  sidebarPanel(
149
  if (!is.null(LOAD_ERROR)) {
 
151
  style = "color:#b00020; font-weight:600;",
152
  paste0("データ読込エラー: ", LOAD_ERROR),
153
  tags$br(),
154
+ "同じフォルダに ac_date_contract_list.csv / ac_date_guard_master.csv / ac_date_availability.csv を置いているか確認する。"
155
  )
156
  } else {
157
  tagList(
 
159
  dateRangeInput(
160
  "date_range",
161
  "対象期間",
162
+ start = as.Date("2025-01-01"),
163
+ end = as.Date("2025-03-31"),
164
+ min = as.Date("2025-01-01"),
165
+ max = as.Date("2025-12-31"),
166
  format = "yyyy/mm/dd",
167
  language = "ja",
168
  separator = " ~ "
169
  ),
170
  hr(),
171
  h4("🗺️ 表示設定"),
172
+ checkboxInput("show_guards", "割当済み隊員を表示", TRUE),
173
  radioButtons(
174
  "match_mode",
175
+ "追加マッチング方法(未割当隊員の参考)",
176
  choices = c("市区町村一致" = "city", "距離(半径km)" = "dist"),
177
  selected = "city"
178
  ),
 
198
  ),
199
  tags$div(class = "legend-item",
200
  tags$div(class = "legend-color", style = "background-color: #3498db; opacity: 0.7;"),
201
+ tags$span("割当済み隊員")
202
  )
203
+ ),
204
+ hr(),
205
+ helpText("※ 対応可能人数 = 日付×契約IDが一致する担当予定の隊員数をカウント")
206
  )
207
  },
208
  width = 3
 
212
  fluidRow(
213
  column(3,
214
  tags$div(class = "summary-header",
215
+ h5("稼働現場数"),
216
  textOutput("stat_sites", inline = TRUE)
217
  )
218
  ),
 
237
  ),
238
  leafletOutput("map", height = 480),
239
  br(),
240
+ h4("現場別 需給状況(選択期間・日付×契約ID別集計)"),
241
  tableOutput("summary"),
242
  width = 9
243
  )
 
266
  d_start <- date_range[1]
267
  d_end <- date_range[2]
268
 
269
+ # 期間内の現場(日付×contract_idの組み合わせ)
270
  active_sites <- contract %>%
271
+ filter(!is.na(対応日)) %>%
272
+ filter(対応>= d_start, 対応<= d_end)
273
 
274
+ # 期間内で担当予定がある隊員(日付×contract_id単位)
275
+ assigned_avail <- avail %>%
276
+ filter(!is.na(日付), 日付 >= d_start, 日付 <= d_end) %>%
277
+ filter(available_flag == 1L, !is.na(担当予定contract_id))
 
278
 
279
+ # 隊員マスターと結合して座標取得
280
+ assigned_guards <- assigned_avail %>%
281
+ inner_join(guard, by = "ユーザー番号")
282
 
283
  list(
284
  date_start = d_start,
285
  date_end = d_end,
286
  active_sites = active_sites,
287
+ assigned_avail = assigned_avail,
288
+ assigned_guards = assigned_guards
289
  )
290
  })
291
 
292
+ # 需給サマリー計算(日付×contract_id別)
293
  summary_tbl <- reactive({
294
  dd <- daily()
295
  sites <- dd$active_sites
296
+ assigned <- dd$assigned_avail
297
 
298
  if (nrow(sites) == 0) {
299
  return(data.frame(メッセージ = "選択期間に稼働中の現場がない", stringsAsFactors = FALSE))
300
  }
301
 
302
+ # 日付×contract_id別の割当済み隊員数をカウント
303
+ assigned_count <- assigned %>%
304
+ count(日付, 担当予定contract_id, name = "assigned_guards")
305
+
306
+ # 現場データと結合
307
+ result <- sites %>%
308
+ left_join(
309
+ assigned_count,
310
+ by = c("対応日" = "日付", "contract_id" = "担当予定contract_id")
311
+ ) %>%
312
+ mutate(
313
+ assigned_guards = ifelse(is.na(assigned_guards), 0L, assigned_guards),
314
+ shortage = pmax(required_guards - assigned_guards, 0L),
315
+ fulfillment_rate = round(assigned_guards / required_guards * 100, 0)
316
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
 
318
  # 色と状態を追加
319
  result <- result %>%
 
329
  result
330
  })
331
 
332
+ # 表示用テーブル(日付×契約ID別)
333
  output$summary <- renderTable({
334
  tbl <- summary_tbl()
335
  if ("メッセージ" %in% colnames(tbl)) return(tbl)
336
 
337
  tbl %>%
338
  transmute(
339
+ 対応日 = format(対応日, "%Y/%m/%d"),
340
  契約ID = contract_id,
341
  契約No = `契約No`,
342
  顧客 = `顧客`,
343
+ 件名 = paste0(`件名1`, ifelse(is.na(`件名2`) | trimws(`件名2`) == "" | `件名2` == "NA", "", paste0(" ", `件名2`))),
344
  市区町村 = site_city,
345
  必要人数 = required_guards,
346
+ 対応可能 = as.integer(assigned_guards),
347
  充足率 = paste0(fulfillment_rate, "%"),
348
  状態 = status
349
+ ) %>%
350
+ arrange(対応日, 契約ID)
351
  })
352
 
353
  # サマリー統計
354
  output$stat_sites <- renderText({
355
+ tbl <- summary_tbl()
356
+ if ("メッセージ" %in% colnames(tbl)) return("-")
357
+ # ユニークな日付×契約IDの組み合わせ数
358
+ paste0(nrow(tbl), " 件(日付×契約ID)")
359
  })
360
 
361
  output$stat_required <- renderText({
 
365
  })
366
 
367
  output$stat_available <- renderText({
368
+ tbl <- summary_tbl()
369
+ if ("メッセージ" %in% colnames(tbl)) return("-")
370
+ paste0(sum(tbl$assigned_guards, na.rm = TRUE), " 人")
371
  })
372
 
373
  output$stat_avg_rate <- renderText({
 
386
  addTiles() %>%
387
  setView(lng = center_lng, lat = center_lat, zoom = 9) %>%
388
  addLayersControl(
389
+ overlayGroups = c("現場(充足率)", "割当済み隊員"),
390
  options = layersControlOptions(collapsed = FALSE)
391
  )
392
  })
 
395
  observe({
396
  dd <- daily()
397
  sites_data <- summary_tbl()
398
+ gds <- dd$assigned_guards
399
 
400
  proxy <- leafletProxy("map")
401
  proxy %>%
402
  clearGroup("現場(充足率)") %>%
403
+ clearGroup("割当済み隊員")
404
 
405
+ # 現場マーカー(充足率付き)- 地理的にユニークな場所ごとに集約
406
  if (!("メッセージ" %in% colnames(sites_data)) && nrow(sites_data) > 0) {
407
+ # 同じ座標の現場集約(代表値として平均充足率を表示)
408
+ sites_geo <- sites_data %>%
409
+ filter(!is.na(site_lat), !is.na(site_lng)) %>%
410
+ group_by(site_lat, site_lng, site_city, `契約No`, `件名1`) %>%
411
+ summarise(
412
+ avg_rate = round(mean(fulfillment_rate, na.rm = TRUE), 0),
413
+ total_required = sum(required_guards, na.rm = TRUE),
414
+ total_assigned = sum(assigned_guards, na.rm = TRUE),
415
+ n_days = n(),
416
+ .groups = "drop"
417
+ ) %>%
418
+ mutate(
419
+ fill_color = get_fill_color(avg_rate)
 
 
 
 
420
  )
421
 
422
+ if (nrow(sites_geo) > 0) {
 
 
423
  proxy %>%
424
+ addCircleMarkers(
425
+ data = sites_geo,
426
+ lng = ~site_lng, lat = ~site_lat,
427
+ radius = 14,
428
+ color = ~fill_color,
429
+ fillColor = ~fill_color,
430
+ fillOpacity = 0.85,
431
+ weight = 2,
432
+ label = ~paste0(
433
+ "", `契約No`, "", `件名1`,
434
+ " | 平均充足率: ", avg_rate, "%",
435
+ " | 延べ必要: ", total_required, "",
436
+ " | 延べ対応: ", total_assigned, "人",
437
+ " | 対応日数: ", n_days, "日"
 
 
438
  ),
439
  group = "現場(充足率)"
440
  )
441
+
442
+ # 充足率ラベルを個別に追加
443
+ for (i in seq_len(nrow(sites_geo))) {
444
+ row <- sites_geo[i, ]
445
+ proxy %>%
446
+ addLabelOnlyMarkers(
447
+ lng = row$site_lng,
448
+ lat = row$site_lat,
449
+ label = paste0(row$avg_rate, "%"),
450
+ labelOptions = labelOptions(
451
+ noHide = TRUE,
452
+ direction = "top",
453
+ textOnly = TRUE,
454
+ style = list(
455
+ "font-weight" = "bold",
456
+ "font-size" = "11px",
457
+ "color" = "white",
458
+ "background-color" = row$fill_color,
459
+ "padding" = "2px 5px",
460
+ "border-radius" = "4px"
461
+ )
462
+ ),
463
+ group = "現場(充足率)"
464
+ )
465
+ }
466
  }
467
  }
468
 
469
+ # 割当済み隊員マーカー(ユニークな隊員のみ表示)
 
470
  if (isTRUE(input$show_guards) && nrow(gds) > 0) {
471
+ gds_unique <- gds %>%
472
+ filter(!is.na(home_lat), !is.na(home_lng)) %>%
473
+ distinct(ユーザー番号, .keep_all = TRUE)
474
+
475
+ if (nrow(gds_unique) > 0) {
476
+ proxy %>%
477
+ addCircleMarkers(
478
+ data = gds_unique,
479
+ lng = ~home_lng, lat = ~home_lat,
480
+ radius = 6,
481
+ color = "#3498db",
482
+ fillColor = "#3498db",
483
+ fillOpacity = 0.6,
484
+ weight = 1,
485
+ label = ~paste0("ユーザー番号: ", ユーザー番号, " | ", 苗字, " ", 名前, " | ", guard_city),
486
+ group = "割当済み隊員"
487
+ )
488
+ }
489
  }
490
  })
491
  }
492
 
493
  shinyApp(ui, server)