Compare commits
187 commits
Author | SHA1 | Date | |
---|---|---|---|
|
f1914082b8 | ||
|
6016948329 | ||
|
708db1a75c | ||
|
994e881ba6 | ||
|
893e20c27b | ||
|
23aace6149 | ||
|
e774e6a038 | ||
|
f19a1a5960 | ||
|
03156d62f6 | ||
|
04d01dc781 | ||
|
cfae8807aa | ||
|
f90e77987e | ||
|
2ed0738b30 | ||
|
74c5664a7f | ||
|
4c9abe3d84 | ||
|
7a45394820 | ||
|
588a48e65d | ||
|
83453e2464 | ||
|
e6809585c9 | ||
|
14bf63e21d | ||
|
b5d932866a | ||
|
0b8a84a57c | ||
|
3555b4ce20 | ||
|
8cad976e7f | ||
|
ad7b6a8ec2 | ||
|
906ecfb6a1 | ||
|
03cc3a1ad2 | ||
|
d62dbd48ae | ||
|
cb12945270 | ||
|
af74854b8e | ||
|
f35fae109b | ||
|
804b2130a8 | ||
|
49537a2efe | ||
|
1dfb4ddcd8 | ||
|
fb7969e046 | ||
|
cd4863b974 | ||
|
55f4a81dee | ||
|
d006df8d7c | ||
|
97095733dd | ||
|
d08b0ce47a | ||
|
caa5a7e6b7 | ||
|
9376c02158 | ||
|
1ebd639e36 | ||
|
eff34725af | ||
|
00d4bfd712 | ||
|
5f9e285c70 | ||
|
902824cdbd | ||
|
d3cbf9a8ff |
||
|
c63704ba0d | ||
|
da404d6435 | ||
|
d9a6c4f211 | ||
|
7436997f9b | ||
|
4c2be68549 | ||
|
6d1766d81a | ||
|
3e676d2073 | ||
|
6da73d73a5 | ||
|
b9c98205e0 | ||
|
07d2f5b6a0 | ||
|
bfa479507c | ||
|
4182728901 | ||
|
5be5709043 | ||
|
ee5a2ec289 | ||
|
cdfb95f425 | ||
|
451060cb65 | ||
|
4d795e13cd | ||
|
ff6bf235aa | ||
|
a272127a00 | ||
|
e3bc6de734 | ||
|
23249de728 | ||
|
05e4af9ae7 | ||
|
1864a79f99 | ||
|
5843a881e6 | ||
|
d898fbb4b0 | ||
|
721767331b | ||
|
abd4c1a1ad | ||
|
df971b1289 | ||
|
e5c81eefd2 | ||
|
49c7c033d9 | ||
|
f7fb238fb4 | ||
|
52dbd8d708 | ||
|
427babf34e | ||
|
1022879103 | ||
|
dbf34e6740 | ||
|
4fd062b4e3 | ||
|
9aa8050627 | ||
|
cd310626e9 | ||
|
145c2ca4a4 | ||
|
1f5dcef29d | ||
|
899c1d98e3 | ||
|
3f8ea405bf | ||
|
f3c9a91da8 | ||
|
a6c79cd5d8 | ||
|
ed1174affb | ||
|
451f101350 | ||
|
a29fe1681d | ||
|
48e142c47d | ||
|
f1bc0164f6 | ||
|
aceb282f8d | ||
|
7871c118e7 | ||
|
5e7b379a45 | ||
|
be95311471 | ||
|
17d7083412 | ||
|
51e5c55d5f | ||
|
88dacc00f7 | ||
|
c314c9f6ec | ||
|
2b54f0a7f3 | ||
|
7a5fe59dbf | ||
|
a63587bb19 | ||
|
eb46343ce8 | ||
|
8fa43fb9f7 | ||
|
6d5e9ad4a1 | ||
|
70c8228605 | ||
|
82470bd995 | ||
|
a263558383 | ||
|
7d82e35650 | ||
|
8616bcedd4 | ||
|
2c66322121 | ||
|
1402bc883e | ||
|
1325822798 | ||
|
7a786d4c0e | ||
|
87c7afac16 | ||
|
06d39579a5 | ||
|
c8ea0a73e2 | ||
|
eeb3c88131 | ||
|
fd718b61ac | ||
|
4a3b2a0014 | ||
|
cbd87dcc38 | ||
|
956de03a62 | ||
|
2b74098040 | ||
|
402a9e1ee0 | ||
|
e68653463d | ||
|
0715962ec5 | ||
|
5668a3bcfd | ||
|
bd241dcbe0 | ||
|
69786b3968 | ||
|
6e2ded5d33 | ||
|
b47d5f7fa1 | ||
|
90ff73d45f | ||
|
c2c7015f39 | ||
|
579602419e | ||
|
28857e7fac | ||
|
6d23fb1b61 | ||
|
96332978a0 | ||
|
ad95fbfd4a | ||
|
1488c0a0fc | ||
|
d9d8cbacec | ||
|
80f2adad50 | ||
|
7a72f4a05b | ||
|
6d7ff628d8 | ||
|
e9f9f66b2f | ||
|
6ca88f98af | ||
|
631cf776f6 | ||
|
6ea9b4b94a | ||
|
d835c168d3 | ||
|
329786365d | ||
|
4f6380a73c | ||
|
cde1217356 | ||
|
2eedfca78a | ||
|
0d65984991 | ||
|
2a932fe7e8 | ||
|
0e02171938 | ||
|
a3dfa05f25 | ||
|
2a3b0304cb | ||
|
16e35f68bb | ||
|
74b1c846a5 | ||
|
1f930c18e4 | ||
|
d9e60eff6b | ||
|
097982334c | ||
|
be6e6b910e | ||
|
31b9ec1116 | ||
|
ff6c3b70d3 | ||
|
0fd0b31a60 | ||
|
76e6ebc63c | ||
|
2ea35adb98 | ||
|
782f63f510 | ||
|
c874122fc0 | ||
|
2efda4933d | ||
|
b7c70d750a | ||
|
5ebfac6cc8 | ||
|
74ca6149e3 | ||
|
40d7590f80 | ||
|
2cb27240dc | ||
|
837c2683df | ||
|
0b278c7db8 | ||
|
0b765d10fe | ||
|
20dbdfb344 | ||
|
426448ed98 |
4
.github/ISSUE_TEMPLATE.md
vendored
|
@ -2,4 +2,6 @@
|
||||||
|
|
||||||
|
|
||||||
Provide a description of the feature request or bug, the more details the better.
|
Provide a description of the feature request or bug, the more details the better.
|
||||||
Please use https://forums.sonarr.tv/ for support or other questions. (When in doubt, use the forums)
|
When possible include a log!
|
||||||
|
|
||||||
|
Please use our [Discord server](https://discord.gg/NWYch8M) for support or longer discussions.
|
||||||
|
|
9
.gitignore
vendored
|
@ -127,9 +127,18 @@ bin
|
||||||
obj
|
obj
|
||||||
output/*
|
output/*
|
||||||
|
|
||||||
|
#Packages
|
||||||
|
Radarr_*/
|
||||||
|
Radarr_*.zip
|
||||||
|
Radarr_*.gz
|
||||||
|
|
||||||
#OS X metadata files
|
#OS X metadata files
|
||||||
._*
|
._*
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
_start
|
_start
|
||||||
_temp_*/**/*
|
_temp_*/**/*
|
||||||
|
|
||||||
|
#AppVeyor
|
||||||
|
/tools-cake/
|
||||||
|
/_artifacts/
|
14
.travis.yml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
language: csharp
|
||||||
|
solution: src/NzbDrone.sln
|
||||||
|
script: # the following commands are just examples, use whatever your build process requires
|
||||||
|
- ./build.sh
|
||||||
|
- chmod +x test.sh
|
||||||
|
# - ./test.sh Linux Unit Takes far too long, maybe even crashes travis :/
|
||||||
|
install:
|
||||||
|
- sudo apt-get install nodejs
|
||||||
|
- sudo apt-get install npm
|
||||||
|
after_success:
|
||||||
|
- chmod +x package.sh
|
||||||
|
- ./package.sh
|
||||||
|
notifications:
|
||||||
|
- webhooks: https://discordapp.com/api/webhooks/266910310219251712/V-QvCcnYkg3O8PMevcAJOJyCgrYkZQoF2pupLDGbaISNUECmYPd6LRwl3avKHsPyfgWP
|
BIN
7za.dll
Normal file
BIN
7za.exe
Normal file
BIN
7zxa.dll
Normal file
BIN
Logo/1024.png
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 156 KiB |
BIN
Logo/128.png
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 14 KiB |
BIN
Logo/16.png
Before Width: | Height: | Size: 707 B After Width: | Height: | Size: 811 B |
BIN
Logo/256.png
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 30 KiB |
BIN
Logo/32.png
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.1 KiB |
BIN
Logo/400.png
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 51 KiB |
BIN
Logo/48.png
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
Logo/512.png
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 68 KiB |
BIN
Logo/64.png
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 5.6 KiB |
BIN
Logo/800.png
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 115 KiB |
572
Logo/Radarr.svg
Normal file
|
@ -0,0 +1,572 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>SVG</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<ellipse id="path-1" cx="512" cy="512" rx="512" ry="512"></ellipse>
|
||||||
|
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="1024" height="1024" fill="white">
|
||||||
|
<use xlink:href="#path-1"></use>
|
||||||
|
</mask>
|
||||||
|
<mask id="mask-4" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="1024" height="1024" fill="white">
|
||||||
|
<use xlink:href="#path-1"></use>
|
||||||
|
</mask>
|
||||||
|
<polygon id="path-5" points="0 0 1007.8334 0 1007.8334 1181.7303 0 1181.7303"></polygon>
|
||||||
|
<polygon id="path-7" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-9" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-11" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-13" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-15" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-17" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-19" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-21" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-23" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-25" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-27" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-29" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-31" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-33" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-35" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-37" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-39" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-41" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-43" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<polygon id="path-45" points="0 0.308593451 979.971467 0.308593451 979.971467 66.8717453 0 66.8717453"></polygon>
|
||||||
|
<path d="M211.257613,211.421878 C134.335253,288.344238 86.7577838,394.611489 86.7577838,511.991053 C86.7577838,629.370617 134.335253,735.637868 211.257613,812.560228 L511.826788,511.991053 L211.257613,211.421878 Z" id="path-47"></path>
|
||||||
|
<path d="M639.447177,208.78225 C562.524817,285.704609 514.947349,391.97186 514.947349,509.351425 C514.947349,626.730989 562.524817,732.99824 639.447177,809.9206 L940.016353,509.351425 L639.447177,208.78225 Z" id="path-49"></path>
|
||||||
|
<ellipse id="path-51" cx="512" cy="512" rx="512" ry="512"></ellipse>
|
||||||
|
<mask id="mask-52" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="1024" height="1024" fill="white">
|
||||||
|
<use xlink:href="#path-51"></use>
|
||||||
|
</mask>
|
||||||
|
</defs>
|
||||||
|
<g id="Logo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="SVG">
|
||||||
|
<mask id="mask-3" fill="white">
|
||||||
|
<use xlink:href="#path-1"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Mask" stroke="#FFC231" mask="url(#mask-2)" stroke-width="40" fill="#050808">
|
||||||
|
<use mask="url(#mask-4)" xlink:href="#path-1"></use>
|
||||||
|
</g>
|
||||||
|
<g id="Grid" mask="url(#mask-3)">
|
||||||
|
<g transform="translate(23.843025, 1.692150)">
|
||||||
|
<mask id="mask-6" fill="white">
|
||||||
|
<use xlink:href="#path-5"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control" stroke="none" fill="none"></g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g id="Group" transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-8" fill="white">
|
||||||
|
<use xlink:href="#path-7"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-8)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g id="Group" transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-10" fill="white">
|
||||||
|
<use xlink:href="#path-9"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-10)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 901.189447)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-12" fill="white">
|
||||||
|
<use xlink:href="#path-11"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-12)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-14" fill="white">
|
||||||
|
<use xlink:href="#path-13"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-14)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 801.270788)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-16" fill="white">
|
||||||
|
<use xlink:href="#path-15"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-16)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-18" fill="white">
|
||||||
|
<use xlink:href="#path-17"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-18)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 700.391372)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-20" fill="white">
|
||||||
|
<use xlink:href="#path-19"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-20)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-22" fill="white">
|
||||||
|
<use xlink:href="#path-21"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-22)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 600.472713)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-24" fill="white">
|
||||||
|
<use xlink:href="#path-23"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-24)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-26" fill="white">
|
||||||
|
<use xlink:href="#path-25"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-26)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 500.554053)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-28" fill="white">
|
||||||
|
<use xlink:href="#path-27"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-28)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-30" fill="white">
|
||||||
|
<use xlink:href="#path-29"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-30)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 400.635394)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-32" fill="white">
|
||||||
|
<use xlink:href="#path-31"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-32)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-34" fill="white">
|
||||||
|
<use xlink:href="#path-33"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-34)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 299.755978)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-36" fill="white">
|
||||||
|
<use xlink:href="#path-35"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-36)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-38" fill="white">
|
||||||
|
<use xlink:href="#path-37"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-38)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 199.837319)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-40" fill="white">
|
||||||
|
<use xlink:href="#path-39"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.91846539e-13 50.2309573 1.73194792e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-40)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-42" fill="white">
|
||||||
|
<use xlink:href="#path-41"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-42)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-6)">
|
||||||
|
<g transform="translate(0.000000, 99.918659)" id="Group">
|
||||||
|
<g transform="translate(0.000000, 0.924454)">
|
||||||
|
<mask id="mask-44" fill="white">
|
||||||
|
<use xlink:href="#path-43"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-44)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(27.861934, 50.883783)">
|
||||||
|
<mask id="mask-46" fill="white">
|
||||||
|
<use xlink:href="#path-45"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Duplicate-control"></g>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="28.8226902 0.308593451 57.6453804 16.9493814 57.6453804 50.2309573 28.8226902 66.8717453 1.95399252e-13 50.2309573 1.76747506e-13 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="951.148777 0.308593451 979.971467 16.9493814 979.971467 50.2309573 951.148777 66.8717453 922.326087 50.2309573 922.326087 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="893.503397 0.308593451 922.326087 16.9493814 922.326087 50.2309573 893.503397 66.8717453 864.680706 50.2309573 864.680706 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="835.858016 0.308593451 864.680706 16.9493814 864.680706 50.2309573 835.858016 66.8717453 807.035326 50.2309573 807.035326 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="778.212636 0.308593451 807.035326 16.9493814 807.035326 50.2309573 778.212636 66.8717453 749.389945 50.2309573 749.389945 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="720.567255 0.308593451 749.389945 16.9493814 749.389945 50.2309573 720.567255 66.8717453 691.744565 50.2309573 691.744565 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="662.921875 0.308593451 691.744565 16.9493814 691.744565 50.2309573 662.921875 66.8717453 634.099185 50.2309573 634.099185 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="605.276494 0.308593451 634.099185 16.9493814 634.099185 50.2309573 605.276494 66.8717453 576.453804 50.2309573 576.453804 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="547.631114 0.308593451 576.453804 16.9493814 576.453804 50.2309573 547.631114 66.8717453 518.808424 50.2309573 518.808424 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="489.985734 0.308593451 518.808424 16.9493814 518.808424 50.2309573 489.985734 66.8717453 461.163043 50.2309573 461.163043 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="432.340353 0.308593451 461.163043 16.9493814 461.163043 50.2309573 432.340353 66.8717453 403.517663 50.2309573 403.517663 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="374.694973 0.308593451 403.517663 16.9493814 403.517663 50.2309573 374.694973 66.8717453 345.872283 50.2309573 345.872283 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="317.049592 0.308593451 345.872283 16.9493814 345.872283 50.2309573 317.049592 66.8717453 288.226902 50.2309573 288.226902 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="259.404212 0.308593451 288.226902 16.9493814 288.226902 50.2309573 259.404212 66.8717453 230.581522 50.2309573 230.581522 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="201.758831 0.308593451 230.581522 16.9493814 230.581522 50.2309573 201.758831 66.8717453 172.936141 50.2309573 172.936141 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="144.113451 0.308593451 172.936141 16.9493814 172.936141 50.2309573 144.113451 66.8717453 115.290761 50.2309573 115.290761 16.9493814"></polygon>
|
||||||
|
<polygon id="Polygon" stroke="#999999" mask="url(#mask-46)" points="86.4680706 0.308593451 115.290761 16.9493814 115.290761 50.2309573 86.4680706 66.8717453 57.6453804 50.2309573 57.6453804 16.9493814"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<mask id="mask-48" fill="white">
|
||||||
|
<use xlink:href="#path-47"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="Combined-Shape" fill="#F1F1F1" xlink:href="#path-47"></use>
|
||||||
|
<mask id="mask-50" fill="white">
|
||||||
|
<use xlink:href="#path-49"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="Combined-Shape" fill="#F1F1F1" transform="translate(727.481851, 509.351425) rotate(-180.000000) translate(-727.481851, -509.351425) " xlink:href="#path-49"></use>
|
||||||
|
<circle id="Oval-2" fill="#FFC231" cx="512.387624" cy="512.387624" r="135.118088"></circle>
|
||||||
|
<path d="M691.584224,554.79626 L741.584224,554.79626 L741.584224,848.113106 L691.584224,848.113106 L691.584224,554.79626 Z M691.584224,668.27622 L707.760695,668.27622 L707.760695,848.113106 L691.584224,848.113106 L691.584224,668.27622 Z M725.407754,668.27622 L741.584224,668.27622 L741.584224,848.113106 L725.407754,848.113106 L725.407754,668.27622 Z" id="Combined-Shape" fill="#FFC231" transform="translate(716.584224, 701.454683) rotate(133.000000) translate(-716.584224, -701.454683) "></path>
|
||||||
|
<path d="M288.802242,169.956176 L338.802242,169.956176 L338.802242,463.273022 L288.802242,463.273022 L288.802242,169.956176 Z M288.802242,283.436136 L304.978713,283.436136 L304.978713,463.273022 L288.802242,463.273022 L288.802242,283.436136 Z M322.625772,283.436136 L338.802242,283.436136 L338.802242,463.273022 L322.625772,463.273022 L322.625772,283.436136 Z" id="Combined-Shape" fill="#FFC231" transform="translate(313.802242, 316.614599) scale(-1, -1) rotate(133.000000) translate(-313.802242, -316.614599) "></path>
|
||||||
|
<path d="M816.093378,100.047294 C731.060203,37.1735645 625.871277,0 512,0 C398.30327,0 293.262295,37.0596891 208.297793,99.7583476 L404.58707,301.155391 C436.776006,284.750117 473.221118,275.499672 511.826788,275.499672 C550.704585,275.499672 587.391258,284.880988 619.746562,301.503373 L816.093378,100.047294 Z" id="Combined-Shape" fill="#F1F1F1"></path>
|
||||||
|
<path d="M816.093378,823.047294 C731.060203,760.173564 625.871277,723 512,723 C398.30327,723 293.262295,760.059689 208.297793,822.758348 L404.58707,1024.15539 C436.776006,1007.75012 473.221118,998.499672 511.826788,998.499672 C550.704585,998.499672 587.391258,1007.88099 619.746562,1024.50337 L816.093378,823.047294 Z" id="Combined-Shape" fill="#F1F1F1" transform="translate(512.195585, 873.751687) scale(1, -1) translate(-512.195585, -873.751687) "></path>
|
||||||
|
<use id="Grid-Mask" stroke="#FFC231" mask="url(#mask-52)" stroke-width="40" xlink:href="#path-51"></use>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 98 KiB |
240
Logo/Sonarr.svg
|
@ -1,240 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="218px"
|
|
||||||
height="218px" viewBox="0 0 218 218" enable-background="new 0 0 218 218" xml:space="preserve">
|
|
||||||
<symbol id="hex_grid" viewBox="-114.25 -98.617 228.55 197.233">
|
|
||||||
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="none" stroke="#989898" stroke-width="0.5" stroke-linecap="square" stroke-miterlimit="1" d="
|
|
||||||
M72.15,90.3l4.7-2.7l4.65,2.7v5.4l-4.65,2.7l-4.7-2.7V90.3z M62.85,95.7l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7V95.7l4.65,2.7
|
|
||||||
l4.65-2.7 M62.85,90.3l4.65-2.7l4.65,2.7 M62.85,79.55v-5.4l4.65-2.7l4.65,2.7v5.4L67.5,82.2L62.85,79.55L58.2,82.2l-4.65-2.65
|
|
||||||
M72.15,74.15l4.7-2.7l4.65,2.7v5.4l-4.65,2.65l-4.7-2.65 M76.85,87.6v-5.4 M67.5,87.6v-5.4 M81.5,95.7l4.65,2.7l4.65-2.7l4.65,2.7
|
|
||||||
l4.65-2.7l4.65,2.7l4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7v-5.4l-4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4
|
|
||||||
l4.65-2.7v-5.4L109.4,31v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7v-5.4l-4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7
|
|
||||||
V-31l-4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7v-5.4l-4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7v-5.4
|
|
||||||
l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.7-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7
|
|
||||||
l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.7-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7L7-98.4l-4.65,2.7l-4.65-2.7
|
|
||||||
l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.7-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7
|
|
||||||
l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.7-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7v5.4l-4.65,2.7
|
|
||||||
v5.4l4.65,2.65v5.4l-4.65,2.7v5.4l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65v5.4l-4.65,2.7v5.4l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65
|
|
||||||
v5.4l-4.65,2.7v5.4l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65v5.4l-4.65,2.7V31l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65v5.4l-4.65,2.7
|
|
||||||
v5.4l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65v5.4l-4.65,2.7v5.4l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.7,2.7
|
|
||||||
l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.7,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7
|
|
||||||
l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7L7,95.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.7,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7
|
|
||||||
l4.65-2.7 M44.25,95.7v-5.4l4.65-2.7l4.65,2.7 M44.25,79.55v-5.4l4.65-2.7l4.65,2.7v5.4L48.9,82.2L44.25,79.55L39.6,82.2
|
|
||||||
l-4.65-2.65 M58.2,87.6v-5.4 M48.9,87.6v-5.4 M53.55,63.35v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7L53.55,63.35l-4.65,2.7l-4.65-2.7
|
|
||||||
v-5.4l4.65-2.7l4.65,2.7 M62.85,74.15l-4.65-2.7v-5.4 M53.55,74.15l4.65-2.7 M48.9,71.45v-5.4 M48.9,55.25v-5.4l4.65-2.65
|
|
||||||
l4.65,2.65v5.4 M67.5,71.45v-5.4l4.65-2.7l4.7,2.7v5.4 M67.5,66.05l-4.65-2.7 M58.2,49.85l4.65-2.65l4.65,2.65v5.4l-4.65,2.7
|
|
||||||
M72.15,63.35v-5.4l4.7-2.7l4.65,2.7v5.4l-4.65,2.7 M76.85,55.25v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M67.5,55.25l4.65,2.7
|
|
||||||
M34.95,95.7v-5.4l4.65-2.7l4.65,2.7 M16.3,95.7v-5.4l4.65-2.7l4.65,2.7v5.4 M25.6,90.3l4.7-2.7l4.65,2.7 M25.6,79.55v-5.4l4.7-2.7
|
|
||||||
l4.65,2.7v5.4L30.3,82.2L25.6,79.55l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M20.95,87.6v-5.4 M39.6,87.6v-5.4 M30.3,87.6
|
|
||||||
v-5.4 M7,95.7v-5.4l4.65-2.7l4.65,2.7 M-2.3,95.7v-5.4l4.65-2.7L7,90.3 M2.35,82.2l-4.65-2.65v-5.4l4.65-2.7L7,74.15v5.4L2.35,82.2
|
|
||||||
z M16.3,79.55l-4.65,2.65L7,79.55 M2.35,87.6v-5.4 M11.65,87.6v-5.4 M16.3,74.15l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M2.35,71.45
|
|
||||||
v-5.4L7,63.35l4.65,2.7 M2.35,49.85L7,47.2l4.65,2.65v5.4L7,57.95l-4.65-2.7V49.85L-2.3,47.2v-5.4l4.65-2.7L7,41.8v5.4
|
|
||||||
M11.65,55.25l4.65,2.7v5.4 M7,74.15l4.65-2.7 M7,57.95v5.4 M30.3,71.45v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M16.3,57.95
|
|
||||||
l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M30.3,66.05l-4.7-2.7 M30.3,49.85l4.65-2.65l4.65,2.65v5.4l-4.65,2.7l-4.65-2.7V49.85l-4.7-2.65
|
|
||||||
v-5.4l-4.65-2.7v-5.4L25.6,31l4.7,2.7v5.4l-4.7,2.7 M11.65,49.85l4.65-2.65l4.65,2.65v5.4 M25.6,57.95l4.7-2.7 M34.95,57.95v5.4
|
|
||||||
M34.95,47.2v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M25.6,31v-5.4l4.7-2.7l4.65,2.7V31l-4.65,2.7 M34.95,25.6l4.65-2.7l4.65,2.7
|
|
||||||
V31l-4.65,2.7L34.95,31 M30.3,39.1l4.65,2.7 M39.6,39.1v-5.4 M20.95,39.1l-4.65,2.7l-4.65-2.7v-5.4L16.3,31l4.65,2.7 M16.3,41.8
|
|
||||||
v5.4 M2.35,33.7L-2.3,31v-5.4l4.65-2.7L7,25.6V31L2.35,33.7z M7,25.6l4.65-2.7l4.65,2.7V31 M2.35,39.1v-5.4 M11.65,33.7L7,31
|
|
||||||
M7,41.8l4.65-2.7 M11.65,17.5L7,14.85v-5.4l4.65-2.7l4.65,2.7v5.4L11.65,17.5z M11.65,22.9v-5.4 M2.35,22.9v-5.4L7,14.85 M7,9.45
|
|
||||||
l-4.65-2.7v-5.4L7-1.35l4.65,2.7v5.4 M34.95,14.85v-5.4l4.65-2.7l4.65,2.7v5.4L39.6,17.5L34.95,14.85z M39.6,22.9v-5.4 M25.6,25.6
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.65l4.7,2.65v5.4 M16.3,9.45l4.65-2.7l4.65,2.7v5.4 M34.95,9.45l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4
|
|
||||||
M11.65,1.35l4.65-2.7l4.65,2.7v5.4 M25.6,9.45l4.7-2.7 M30.3,17.5l4.65-2.65 M16.3,25.6l4.65-2.7 M20.95,17.5l-4.65-2.65
|
|
||||||
M76.85,49.85l-4.7-2.65v-5.4l4.7-2.7l4.65,2.7v5.4 M62.85,47.2v-5.4l4.65-2.7l4.65,2.7 M62.85,25.6l4.65-2.7l4.65,2.7V31
|
|
||||||
l-4.65,2.7L62.85,31V25.6l-4.65-2.7v-5.4 M72.15,25.6l4.7-2.7l4.65,2.7V31l-4.65,2.7l-4.7-2.7 M76.85,39.1v-5.4 M67.5,39.1v-5.4
|
|
||||||
M53.55,47.2v-5.4l4.65-2.7l4.65,2.7 M44.25,41.8l4.65-2.7l4.65,2.7 M44.25,25.6l4.65-2.7l4.65,2.7V31l-4.65,2.7L44.25,31
|
|
||||||
M62.85,31l-4.65,2.7L53.55,31 M58.2,39.1v-5.4 M48.9,39.1v-5.4 M53.55,14.85v-5.4l4.65-2.7l4.65,2.7v5.4L58.2,17.5L53.55,14.85
|
|
||||||
L48.9,17.5l-4.65-2.65 M48.9,22.9v-5.4 M53.55,9.45l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M44.25,9.45l4.65-2.7 M76.85,22.9v-5.4
|
|
||||||
l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M76.85,17.5l-4.7-2.65v-5.4l4.7-2.7l4.65,2.7v5.4 M67.5,22.9v-5.4l4.65-2.65 M67.5,17.5
|
|
||||||
l-4.65-2.65 M72.15,9.45l-4.65-2.7v-5.4l4.65-2.7l4.7,2.7v5.4 M62.85,9.45l4.65-2.7 M53.55,25.6l4.65-2.7 M44.25,63.35l-4.65,2.7
|
|
||||||
M39.6,55.25l4.65,2.7 M39.6,71.45l4.65,2.7 M67.5,49.85l4.65-2.65 M48.9,49.85l-4.65-2.65 M25.6,47.2l-4.65,2.65 M104.75,87.6
|
|
||||||
l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65V87.6l4.65,2.7 M109.4,79.55l-4.65,2.65 M100.1,95.7v-5.4 M81.5,90.3l4.65-2.7
|
|
||||||
l4.65,2.7v5.4 M81.5,74.15l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65 M90.8,79.55l4.65,2.65 M86.15,87.6v-5.4 M90.8,90.3
|
|
||||||
l4.65-2.7 M95.45,71.45v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7L95.45,71.45l-4.65,2.7 M86.15,55.25l4.65,2.7v5.4l-4.65,2.7
|
|
||||||
l-4.65-2.7 M86.15,71.45v-5.4 M95.45,55.25v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7L95.45,55.25l-4.65,2.7 M100.1,63.35v-5.4
|
|
||||||
M90.8,63.35l4.65,2.7 M109.4,63.35l-4.65,2.7 M104.75,71.45l4.65,2.7 M104.75,55.25l4.65,2.7 M100.1,79.55v-5.4 M100.1,47.2v-5.4
|
|
||||||
l4.65-2.7l4.65,2.7 M100.1,41.8l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M109.4,31l-4.65,2.7 M81.5,41.8l4.65-2.7l4.65,2.7v5.4
|
|
||||||
l-4.65,2.65 M86.15,22.9l4.65,2.7V31l-4.65,2.7L81.5,31 M100.1,31v-5.4l4.65-2.7l4.65,2.7 M90.8,31l4.65,2.7 M86.15,39.1v-5.4
|
|
||||||
M90.8,41.8l4.65-2.7 M86.15,17.5l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M90.8,14.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65
|
|
||||||
M81.5,9.45l4.65-2.7l4.65,2.7 M86.15,6.75v-5.4l4.65-2.7l4.65,2.7v5.4 M100.1,14.85l4.65,2.65v5.4 M109.4,14.85l-4.65,2.65
|
|
||||||
M100.1,9.45l4.65-2.7l4.65,2.7 M95.45,1.35l4.65-2.7l4.65,2.7v5.4 M95.45,22.9l4.65,2.7 M109.4,47.2l-4.65,2.65 M90.8,47.2
|
|
||||||
l4.65,2.65 M104.75-9.45l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65V-9.45l4.65,2.7 M109.4-17.5l-4.65,2.65 M100.1-1.35v-5.4
|
|
||||||
M90.8-1.35v-5.4l4.65-2.7 M81.5-6.75l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4L81.5-6.75v5.4l-4.65,2.7 M90.8-6.75l-4.65-2.7
|
|
||||||
M95.45-14.85L90.8-17.5v-5.4l4.65-2.7l4.65,2.7v5.4 M76.85-14.85l-4.7-2.65v-5.4l4.7-2.7l4.65,2.7v5.4 M86.15-14.85l4.65-2.65
|
|
||||||
M95.45-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L95.45-31z M95.45-25.6V-31 M90.8-22.9l-4.65-2.7V-31l4.65-2.7 M86.15-31
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M86.15-41.8v-5.4l4.65-2.65l4.65,2.65v5.4 M100.1-33.7l4.65,2.7v5.4l-4.65,2.7 M109.4-33.7
|
|
||||||
l-4.65,2.7 M95.45-47.2l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M104.75-41.8l4.65,2.7 M81.5-22.9l4.65-2.7 M104.75-25.6l4.65,2.7
|
|
||||||
M100.1-49.85v-5.4l4.65-2.7l4.65,2.7 M109.4-66.05l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M104.75-63.35v5.4 M100.1-55.25
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.7 M86.15-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M86.15-74.15l4.65,2.7v5.4l-4.65,2.7l-4.65-2.7v-5.4
|
|
||||||
L86.15-74.15v-5.4l4.65-2.65l4.65,2.65 M90.8-71.45l4.65-2.7l4.65,2.7 M95.45-63.35l-4.65-2.7 M90.8-55.25l4.65-2.7 M86.15-57.95
|
|
||||||
v-5.4 M95.45-74.15v-5.4l4.65-2.65l4.65,2.65v5.4 M81.5-71.45l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65 M81.5-82.2v-5.4l4.65-2.7
|
|
||||||
l4.65,2.7v5.4 M86.15-90.3v-5.4 M104.75-95.7v5.4l-4.65,2.7l-4.65-2.7v-5.4 M100.1-82.2v-5.4 M95.45-90.3l-4.65,2.7 M109.4-82.2
|
|
||||||
l-4.65,2.65 M104.75-90.3l4.65,2.7 M109.4-49.85l-4.65,2.65 M72.15-1.35v-5.4l4.7-2.7 M67.5,1.35l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7
|
|
||||||
M72.15-17.5l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M67.5-14.85v5.4 M53.55-1.35v-5.4l4.65-2.7l4.65,2.7 M48.9,1.35
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M44.25-22.9l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65V-22.9l-4.65-2.7V-31 M53.55-17.5
|
|
||||||
l4.65,2.65v5.4 M48.9-9.45v-5.4 M53.55-33.7v-5.4l4.65-2.7l4.65,2.7v5.4L58.2-31L53.55-33.7z M62.85-22.9l-4.65-2.7V-31 M48.9-25.6
|
|
||||||
V-31l4.65-2.7 M48.9-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M48.9-41.8v-5.4l4.65-2.65l4.65,2.65v5.4 M76.85-25.6V-31l4.65-2.7
|
|
||||||
M76.85-31l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7 M62.85-33.7L67.5-31v5.4 M72.15-39.1l-4.65-2.7v-5.4l4.65-2.65l4.7,2.65v5.4
|
|
||||||
M62.85-39.1l4.65-2.7 M72.15-33.7L67.5-31 M53.55-22.9l4.65-2.7 M58.2-14.85l4.65-2.65 M30.3,1.35l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7
|
|
||||||
v5.4 M30.3-9.45v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M16.3-1.35v-5.4l4.65-2.7l4.65,2.7 M30.3-14.85l-4.7-2.65v-5.4l4.7-2.7
|
|
||||||
l4.65,2.7v5.4 M25.6-17.5l-4.65,2.65L16.3-17.5v-5.4l4.65-2.7l4.65,2.7 M20.95-14.85v5.4 M16.3-6.75l-4.65-2.7v-5.4l4.65-2.65
|
|
||||||
M2.35,1.35l-4.65-2.7v-5.4l4.65-2.7L7-6.75v5.4 M7-17.5l-4.65,2.65L-2.3-17.5v-5.4l4.65-2.7L7-22.9V-17.5l4.65,2.65 M11.65-9.45
|
|
||||||
L7-6.75 M2.35-9.45v-5.4 M11.65-31L7-33.7v-5.4l4.65-2.7l4.65,2.7v5.4L11.65-31z M16.3-22.9l-4.65-2.7V-31 M2.35-25.6V-31L7-33.7
|
|
||||||
M7-39.1l-4.65-2.7v-5.4L7-49.85l4.65,2.65v5.4 M44.25-33.7L39.6-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M20.95-25.6V-31l4.65-2.7
|
|
||||||
l4.7,2.7v5.4 M20.95-47.2l4.65-2.65l4.7,2.65v5.4l-4.7,2.7l-4.65-2.7V-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M30.3-47.2
|
|
||||||
l4.65-2.65l4.65,2.65v5.4 M30.3-41.8l4.65,2.7 M25.6-33.7v-5.4 M34.95-33.7L30.3-31 M34.95-22.9l4.65-2.7 M20.95-31l-4.65-2.7
|
|
||||||
M16.3-39.1l4.65-2.7 M7-22.9l4.65-2.7 M34.95-55.25l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L34.95-55.25v5.4 M25.6-49.85v-5.4
|
|
||||||
l4.7-2.7 M30.3-63.35l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7v5.4 M25.6-66.05l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M30.3-74.15
|
|
||||||
v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M20.95-63.35v5.4 M7-49.85v-5.4l4.65-2.7l4.65,2.7 M2.35-47.2l-4.65-2.65v-5.4l4.65-2.7
|
|
||||||
L7-55.25 M2.35-63.35l-4.65-2.7v-5.4l4.65-2.7L7-71.45v5.4L2.35-63.35z M16.3-71.45l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4
|
|
||||||
M11.65-57.95v-5.4l4.65-2.7 M2.35-57.95v-5.4 M7-66.05l4.65,2.7 M11.65-74.15L7-71.45 M2.35-74.15v-5.4L7-82.2l4.65,2.65
|
|
||||||
M11.65-95.7v5.4L7-87.6l-4.65-2.7v-5.4 M20.95-95.7v5.4l-4.65,2.7l-4.65-2.7 M7-87.6v5.4 M16.3-87.6v5.4 M20.95-90.3l4.65,2.7v5.4
|
|
||||||
l-4.65,2.65 M30.3-79.55l-4.7-2.65 M30.3-95.7v5.4l-4.7,2.7 M48.9-95.7v5.4l-4.65,2.7l-4.65-2.7v-5.4 M34.95-82.2v-5.4l4.65-2.7
|
|
||||||
M30.3-90.3l4.65,2.7 M72.15-49.85v-5.4l4.7-2.7l4.65,2.7 M67.5-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M67.5-74.15l4.65,2.7v5.4
|
|
||||||
l-4.65,2.7l-4.65-2.7v-5.4L67.5-74.15v-5.4l4.65-2.65l4.7,2.65 M81.5-66.05l-4.65,2.7l-4.7-2.7 M72.15-71.45l4.7-2.7 M76.85-63.35
|
|
||||||
v5.4 M67.5-57.95v-5.4 M53.55-49.85v-5.4l4.65-2.7l4.65,2.7 M48.9-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M44.25-66.05v-5.4
|
|
||||||
l4.65-2.7l4.65,2.7v5.4l-4.65,2.7L44.25-66.05l-4.65,2.7 M62.85-66.05l-4.65,2.7l-4.65-2.7 M53.55-71.45l4.65-2.7l4.65,2.7
|
|
||||||
M58.2-57.95v-5.4 M48.9-57.95v-5.4 M48.9-74.15v-5.4l4.65-2.65l4.65,2.65v5.4 M48.9-79.55l-4.65-2.65v-5.4 M58.2-95.7v5.4
|
|
||||||
l-4.65,2.7l-4.65-2.7 M53.55-87.6v5.4 M58.2-79.55l4.65-2.65l4.65,2.65 M62.85-82.2v-5.4l4.65-2.7l4.65,2.7v5.4 M67.5-90.3v-5.4
|
|
||||||
M76.85-95.7v5.4l-4.7,2.7 M58.2-90.3l4.65,2.7 M44.25-17.5l-4.65,2.65 M39.6-9.45l4.65,2.7 M39.6-74.15l4.65,2.7 M39.6-57.95
|
|
||||||
l4.65,2.7 M44.25-49.85L39.6-47.2 M62.85-49.85L58.2-47.2 M16.3-49.85l-4.65,2.65 M44.25-82.2l-4.65,2.65 M76.85-90.3l4.65,2.7
|
|
||||||
M81.5-49.85l-4.65,2.65 M86.15,1.35l-4.65-2.7 M44.25-1.35l-4.65,2.7 M62.85-1.35l-4.65,2.7 M109.4-1.35l-4.65,2.7 M25.6-1.35
|
|
||||||
l-4.65,2.7 M-95.4,95.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-86.1,90.3l4.7-2.7l4.65,2.7v5.4 M-104.7,95.7v-5.4l4.65-2.7l4.65,2.7
|
|
||||||
M-100.05,82.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4L-100.05,82.2z M-95.4,74.15l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65
|
|
||||||
M-86.1,74.15l4.7-2.7l4.65,2.7v5.4l-4.65,2.65l-4.7-2.65 M-100.05,87.6v-5.4 M-90.75,87.6v-5.4 M-81.4,87.6v-5.4 M-109.35,87.6
|
|
||||||
l4.65,2.7 M-104.7,79.55l-4.65,2.65 M-109.35,55.25l4.65,2.7v5.4l-4.65,2.7 M-109.35,71.45l4.65,2.7 M-90.75,66.05l-4.65-2.7v-5.4
|
|
||||||
l4.65-2.7l4.65,2.7v5.4L-90.75,66.05v5.4 M-86.1,57.95l4.7-2.7l4.65,2.7v5.4l-4.65,2.7l-4.7-2.7 M-81.4,71.45v-5.4 M-100.05,71.45
|
|
||||||
v-5.4l4.65-2.7 M-95.4,57.95l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-81.4,55.25v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7
|
|
||||||
M-100.05,66.05l-4.65-2.7 M-104.7,57.95l4.65-2.7 M-86.1,41.8l-4.65-2.7v-5.4l4.65-2.7l4.7,2.7v5.4L-86.1,41.8z M-81.4,49.85
|
|
||||||
l-4.7-2.65v-5.4 M-100.05,49.85l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M-95.4,31l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7V31
|
|
||||||
l4.65,2.7 M-86.1,31v-5.4l4.7-2.7l4.65,2.7V31l-4.65,2.7 M-100.05,39.1v-5.4 M-90.75,39.1l-4.65,2.7 M-109.35,39.1l4.65,2.7
|
|
||||||
M-104.7,31l-4.65,2.7 M-109.35,6.75l4.65,2.7v5.4l-4.65,2.65 M-86.1,14.85v-5.4l4.7-2.7l4.65,2.7v5.4l-4.65,2.65L-86.1,14.85z
|
|
||||||
M-81.4,22.9v-5.4 M-86.1,25.6l-4.65-2.7v-5.4l4.65-2.65 M-100.05,22.9v-5.4l4.65-2.65l4.65,2.65 M-100.05,6.75v-5.4l4.65-2.7
|
|
||||||
l4.65,2.7v5.4l-4.65,2.7L-100.05,6.75z M-81.4,6.75v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M-90.75,6.75l4.65,2.7 M-95.4,14.85v-5.4
|
|
||||||
M-95.4,25.6l4.65-2.7 M-100.05,17.5l-4.65-2.65 M-104.7,9.45l4.65-2.7 M-109.35,22.9l4.65,2.7 M-86.1,47.2l-4.65,2.65
|
|
||||||
M-104.7,47.2l-4.65,2.65 M-11.6,95.7v-5.4l4.65-2.7l4.65,2.7 M-20.9,95.7v-5.4l4.65-2.7l4.65,2.7 M-16.25,82.2l-4.65-2.65v-5.4
|
|
||||||
l4.65-2.7l4.65,2.7v5.4L-16.25,82.2v5.4 M-2.3,79.55l-4.65,2.65l-4.65-2.65 M-6.95,82.2v5.4 M-30.2,95.7v-5.4l4.65-2.7l4.65,2.7
|
|
||||||
M-39.55,95.7v-5.4l4.7-2.7l4.65,2.7 M-39.55,79.55v-5.4l4.7-2.7l4.65,2.7v5.4l-4.65,2.65L-39.55,79.55l-4.65,2.65l-4.65-2.65
|
|
||||||
M-20.9,79.55l-4.65,2.65l-4.65-2.65 M-34.85,87.6v-5.4 M-25.55,87.6v-5.4 M-20.9,74.15l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4
|
|
||||||
M-30.2,74.15l4.65-2.7 M-25.55,66.05l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-39.55,74.15l-4.65-2.7v-5.4l4.65-2.7l4.7,2.7v5.4
|
|
||||||
M-30.2,57.95l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-39.55,63.35v-5.4l4.7-2.7 M-30.2,63.35l-4.65,2.7 M-11.6,74.15l4.65-2.7
|
|
||||||
l4.65,2.7 M-6.95,66.05l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L-6.95,66.05v5.4 M-16.25,66.05l4.65-2.7 M-11.6,57.95l-4.65-2.7v-5.4
|
|
||||||
l4.65-2.65l4.65,2.65v5.4 M-16.25,55.25l-4.65,2.7 M-48.85,95.7v-5.4l4.65-2.7l4.65,2.7 M-58.15,95.7v-5.4l4.65-2.7l4.65,2.7
|
|
||||||
M-58.15,79.55v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65L-58.15,79.55l-4.65,2.65l-4.65-2.65 M-44.2,87.6v-5.4 M-53.5,87.6v-5.4
|
|
||||||
M-67.45,95.7v-5.4l4.65-2.7l4.65,2.7 M-76.75,90.3l4.65-2.7l4.65,2.7 M-76.75,74.15l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65
|
|
||||||
M-62.8,87.6v-5.4 M-72.1,87.6v-5.4 M-67.45,74.15l4.65-2.7l4.65,2.7 M-62.8,71.45v-5.4l4.65-2.7l4.65,2.7v5.4 M-62.8,66.05
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-76.75,63.35l4.65,2.7v5.4 M-62.8,55.25v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7
|
|
||||||
M-67.45,63.35l-4.65,2.7 M-72.1,55.25l4.65,2.7 M-48.85,74.15l4.65-2.7 M-44.2,66.05l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7
|
|
||||||
M-53.5,49.85l4.65-2.65l4.65,2.65v5.4 M-53.5,66.05l4.65-2.7 M-53.5,55.25l4.65,2.7 M-48.85,47.2v-5.4l4.65-2.7l4.65,2.7v5.4
|
|
||||||
l-4.65,2.65 M-58.15,47.2v-5.4l4.65-2.7l4.65,2.7 M-58.15,25.6l4.65-2.7l4.65,2.7V31l-4.65,2.7l-4.65-2.7V25.6l-4.65-2.7v-5.4
|
|
||||||
M-48.85,25.6l4.65-2.7l4.65,2.7V31l-4.65,2.7l-4.65-2.7 M-44.2,39.1v-5.4 M-53.5,39.1v-5.4 M-62.8,49.85l-4.65-2.65v-5.4l4.65-2.7
|
|
||||||
l4.65,2.7 M-76.75,47.2v-5.4l4.65-2.7l4.65,2.7 M-76.75,25.6l4.65-2.7l4.65,2.7V31l-4.65,2.7l-4.65-2.7 M-58.15,31l-4.65,2.7
|
|
||||||
l-4.65-2.7 M-72.1,39.1v-5.4 M-62.8,39.1v-5.4 M-67.45,14.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65L-67.45,14.85l-4.65,2.65
|
|
||||||
l-4.65-2.65 M-72.1,22.9v-5.4 M-62.8,6.75v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M-72.1,6.75l4.65,2.7 M-44.2,22.9v-5.4l4.65-2.65
|
|
||||||
l4.7,2.65v5.4l-4.7,2.7 M-44.2,17.5l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M-48.85,14.85l-4.65,2.65l-4.65-2.65 M-53.5,22.9v-5.4
|
|
||||||
M-44.2,6.75v-5.4l4.65-2.7l4.7,2.7v5.4l-4.7,2.7 M-53.5,6.75l4.65,2.7 M-67.45,25.6l4.65-2.7 M-11.6,47.2v-5.4l4.65-2.7l4.65,2.7
|
|
||||||
M-11.6,41.8l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-16.25,33.7L-20.9,31v-5.4l4.65-2.7l4.65,2.7V31 M-2.3,31l-4.65,2.7
|
|
||||||
M-30.2,47.2v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M-39.55,41.8l4.7-2.7l4.65,2.7 M-34.85,22.9l4.65,2.7V31l-4.65,2.7l-4.7-2.7
|
|
||||||
M-20.9,31l-4.65,2.7L-30.2,31 M-34.85,39.1v-5.4 M-25.55,39.1v-5.4 M-20.9,25.6l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4
|
|
||||||
M-25.55,17.5l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M-25.55,6.75v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M-30.2,14.85l-4.65,2.65
|
|
||||||
M-34.85,6.75l4.65,2.7 M-6.95,17.5l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4L-6.95,17.5v5.4l-4.65,2.7 M-11.6,14.85l-4.65,2.65
|
|
||||||
M-16.25,6.75l4.65,2.7 M-16.25,1.35l4.65-2.7l4.65,2.7v5.4 M-6.95,22.9l4.65,2.7 M-30.2,25.6l4.65-2.7 M-16.25,39.1l-4.65,2.7
|
|
||||||
M-67.45,47.2l-4.65,2.65 M-2.3,47.2l-4.65,2.65 M-34.85,49.85l-4.7-2.65 M-16.25,49.85l-4.65-2.65 M-81.4,39.1l4.65,2.7
|
|
||||||
M-11.6-1.35v-5.4l4.65-2.7l4.65,2.7 M-11.6-6.75l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-16.25-14.85l-4.65-2.65v-5.4l4.65-2.7
|
|
||||||
l4.65,2.7v5.4 M-2.3-17.5l-4.65,2.65 M-20.9-1.35v-5.4l4.65-2.7 M-20.9-6.75l-4.65-2.7v-5.4l4.65-2.65 M-25.55-9.45l-4.65,2.7
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65 M-30.2-6.75v5.4l-4.65,2.7 M-39.55-1.35v-5.4l4.7-2.7 M-34.85-14.85l-4.7-2.65v-5.4l4.7-2.7
|
|
||||||
l4.65,2.7v5.4 M-30.2-33.7v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7L-30.2-33.7l-4.65,2.7l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7 M-20.9-22.9
|
|
||||||
l-4.65-2.7V-31 M-34.85-25.6V-31 M-39.55-39.1l-4.65-2.7v-5.4l4.65-2.65l4.7,2.65v5.4 M-25.55-41.8v-5.4l4.65-2.65l4.65,2.65v5.4
|
|
||||||
l-4.65,2.7 M-6.95-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L-6.95-31v5.4l-4.65,2.7 M-16.25-25.6V-31l4.65-2.7 M-16.25-41.8
|
|
||||||
l4.65,2.7 M-16.25-47.2l4.65-2.65l4.65,2.65v5.4 M-30.2-22.9l4.65-2.7 M-16.25-31l-4.65-2.7 M-6.95-25.6l4.65,2.7 M-44.2,1.35
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M-58.15-1.35v-5.4l4.65-2.7l4.65,2.7 M-58.15-6.75l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4
|
|
||||||
M-62.8-14.85l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M-39.55-17.5l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M-44.2-9.45v-5.4
|
|
||||||
M-53.5-14.85l4.65-2.65 M-62.8,1.35l-4.65-2.7v-5.4l4.65-2.7 M-76.75-6.75l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4L-76.75-6.75
|
|
||||||
v5.4 M-76.75-17.5v-5.4l4.65-2.7l4.65,2.7 M-67.45-17.5l-4.65,2.65 M-72.1-9.45l4.65,2.7 M-67.45-33.7v-5.4l4.65-2.7l4.65,2.7v5.4
|
|
||||||
L-62.8-31L-67.45-33.7z M-62.8-25.6V-31 M-72.1-25.6V-31l4.65-2.7 M-72.1-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M-76.75-39.1
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-62.8-41.8v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M-44.2-25.6V-31l4.65-2.7 M-44.2-31
|
|
||||||
l-4.65-2.7v-5.4l4.65-2.7 M-48.85-33.7L-53.5-31l-4.65-2.7 M-48.85-22.9l-4.65-2.7V-31 M-53.5-41.8l4.65,2.7 M-58.15-22.9l4.65-2.7
|
|
||||||
M-58.15-49.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M-48.85-55.25l4.65-2.7l4.65,2.7v5.4 M-58.15-71.45l4.65-2.7l4.65,2.7v5.4
|
|
||||||
l-4.65,2.7l-4.65-2.7V-71.45z M-48.85-71.45l4.65-2.7l4.65,2.7v5.4l-4.65,2.7l-4.65-2.7 M-44.2-57.95v-5.4 M-53.5-57.95v-5.4
|
|
||||||
M-76.75-49.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M-67.45-55.25l4.65-2.7l4.65,2.7 M-76.75-55.25l-4.65-2.7v-5.4l4.65-2.7
|
|
||||||
l4.65,2.7v5.4 M-81.4-63.35l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7v5.4 M-81.4-74.15v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7
|
|
||||||
M-58.15-66.05l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M-62.8-57.95v-5.4 M-72.1-74.15l4.65,2.7 M-67.45-66.05l-4.65,2.7
|
|
||||||
M-67.45-82.2v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65L-67.45-82.2l-4.65,2.65 M-76.75-82.2v-5.4l4.65-2.7l4.65,2.7 M-72.1-90.3
|
|
||||||
v-5.4 M-62.8-90.3v-5.4 M-53.5-74.15v-5.4l4.65-2.65l4.65,2.65v5.4 M-58.15-82.2l4.65,2.65 M-58.15-87.6l4.65-2.7l4.65,2.7v5.4
|
|
||||||
M-53.5-90.3v-5.4 M-44.2-95.7v5.4l-4.65,2.7 M-62.8-74.15v-5.4 M-11.6-49.85v-5.4l4.65-2.7l4.65,2.7 M-20.9-49.85v-5.4l4.65-2.7
|
|
||||||
l4.65,2.7 M-16.25-63.35l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L-16.25-63.35v5.4 M-2.3-66.05l-4.65,2.7l-4.65-2.7 M-11.6-71.45
|
|
||||||
l4.65-2.7l4.65,2.7 M-6.95-63.35v5.4 M-25.55-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M-39.55-55.25l4.7-2.7l4.65,2.7
|
|
||||||
M-39.55-71.45l4.7-2.7l4.65,2.7v5.4l-4.65,2.7l-4.7-2.7 M-20.9-71.45l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-20.9-66.05
|
|
||||||
l-4.65,2.7l-4.65-2.7 M-25.55-74.15l-4.65,2.7 M-34.85-63.35v5.4 M-25.55-57.95v-5.4 M-34.85-74.15v-5.4l4.65-2.65l4.65,2.65
|
|
||||||
M-44.2-79.55l4.65-2.65l4.7,2.65 M-39.55-82.2v-5.4l4.7-2.7l4.65,2.7v5.4 M-34.85-90.3v-5.4 M-16.25-95.7v5.4l-4.65,2.7l-4.65-2.7
|
|
||||||
v-5.4 M-25.55-90.3l-4.65,2.7 M-20.9-82.2v-5.4 M-6.95-79.55l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4L-6.95-79.55v5.4 M-16.25-79.55
|
|
||||||
l4.65-2.65 M-11.6-87.6l-4.65-2.7 M-6.95-95.7v5.4 M-44.2-90.3l4.65,2.7 M-62.8-47.2l-4.65-2.65 M-44.2-47.2l-4.65-2.65
|
|
||||||
M-30.2-49.85l-4.65,2.65 M-2.3-49.85l-4.65,2.65 M-95.4-1.35v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M-86.1-6.75l4.7-2.7
|
|
||||||
M-100.05,1.35l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M-95.4-17.5l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7V-17.5z M-95.4-22.9
|
|
||||||
l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65 M-81.4-14.85l-4.7-2.65 M-100.05-9.45v-5.4 M-90.75-14.85v5.4 M-109.35-9.45
|
|
||||||
l4.65,2.7 M-104.7-17.5l-4.65,2.65 M-109.35-41.8l4.65,2.7v5.4l-4.65,2.7 M-90.75-25.6V-31l4.65-2.7l4.7,2.7v5.4l-4.7,2.7
|
|
||||||
M-100.05-25.6V-31l4.65-2.7l4.65,2.7 M-100.05-47.2l4.65-2.65l4.65,2.65v5.4l-4.65,2.7l-4.65-2.7V-47.2l-4.65-2.65 M-90.75-41.8
|
|
||||||
l4.65,2.7v5.4 M-86.1-39.1l4.7-2.7 M-95.4-33.7v-5.4 M-109.35-25.6l4.65,2.7 M-100.05-31l-4.65-2.7 M-104.7-39.1l4.65-2.7
|
|
||||||
M-95.4-49.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M-86.1-55.25l4.7-2.7 M-95.4-55.25l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4
|
|
||||||
M-100.05-63.35l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-95.4-71.45l4.65-2.7l4.65,2.7 M-86.1-66.05l-4.65,2.7 M-109.35-57.95
|
|
||||||
l4.65,2.7v5.4l-4.65,2.65 M-109.35-74.15l4.65,2.7 M-104.7-66.05l-4.65,2.7 M-109.35-90.3l4.65,2.7v5.4l-4.65,2.65 M-81.4-79.55
|
|
||||||
l-4.7-2.65v-5.4l4.7-2.7l4.65,2.7 M-86.1-82.2l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M-100.05-74.15v-5.4l4.65-2.65
|
|
||||||
M-95.4-87.6l-4.65-2.7v-5.4 M-81.4-95.7v5.4 M-90.75-95.7v5.4 M-90.75-79.55v5.4 M-104.7-55.25l4.65-2.7 M-100.05-79.55
|
|
||||||
l-4.65-2.65 M-104.7-87.6l4.65-2.7 M-81.4-47.2l-4.7-2.65 M-76.75-33.7L-81.4-31 M-81.4-25.6l4.65,2.7 M-67.45-1.35l-4.65,2.7
|
|
||||||
M-104.7-1.35l-4.65,2.7 M-81.4,1.35l-4.7-2.7 M-25.55,1.35l-4.65-2.7 M-53.5,1.35l4.65-2.7 M-2.3-1.35l-4.65,2.7 M-2.3,57.95
|
|
||||||
l4.65-2.7 M2.35,66.05l-4.65-2.7 M-2.3-39.1l4.65-2.7 M2.35-31l-4.65-2.7 M2.35-79.55L-2.3-82.2 M-2.3-87.6l4.65-2.7 M-2.3,9.45
|
|
||||||
l4.65-2.7 M2.35,17.5l-4.65-2.65"/>
|
|
||||||
</symbol>
|
|
||||||
<g id="Layer_1">
|
|
||||||
</g>
|
|
||||||
<g id="Layer_6">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#EFEEEE" d="M217.5,108.95c0,29.833-10.533,55.399-31.6,76.7
|
|
||||||
c-0.7,0.833-1.484,1.6-2.351,2.3c-3.466,3.399-7.134,6.483-11,9.25c-18.267,13.467-39.366,20.2-63.3,20.2
|
|
||||||
c-23.967,0-45.033-6.733-63.2-20.2c-4.8-3.4-9.3-7.25-13.5-11.55c-16.367-16.267-26.417-35.167-30.15-56.7
|
|
||||||
c-0.733-4.2-1.217-8.467-1.45-12.8c-0.1-2.4-0.15-4.801-0.15-7.2c0-2.534,0.05-4.95,0.15-7.25c0-0.233,0.066-0.467,0.2-0.7
|
|
||||||
c1.567-26.6,12.033-49.583,31.4-68.95C53.85,11.017,79.417,0.5,109.25,0.5c29.934,0,55.483,10.517,76.65,31.55
|
|
||||||
C206.967,53.483,217.5,79.117,217.5,108.95z"/>
|
|
||||||
</g>
|
|
||||||
<g id="Layer_5">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#010101" d="M195.45,43l-22.4,22.4c-8.833,13-13.25,27.867-13.25,44.6
|
|
||||||
c0,17.934,5.067,33.833,15.2,47.7l19,18.95c-2.5,3.066-5.2,6.066-8.1,9c-0.7,0.833-1.484,1.6-2.351,2.3
|
|
||||||
c-2.533,2.5-5.167,4.816-7.899,6.95L158.1,177.35c-13.934-10.733-30.133-16.1-48.6-16.1c-17.933,0-33.833,5.1-47.7,15.3
|
|
||||||
L43.25,195.15c-3.767-2.867-7.333-6.034-10.7-9.5c-2.8-2.801-5.417-5.667-7.85-8.601l19.15-19.2
|
|
||||||
c10.066-13.966,15.1-29.916,15.1-47.85c0-17.5-4.867-33.017-14.6-46.55l-21.05-21c2.833-3.6,5.917-7.067,9.25-10.4
|
|
||||||
c2.934-2.867,5.934-5.55,9-8.05L61.9,44.35C75.7,54.583,91.567,59.7,109.5,59.7c18.467,0,34.666-5.367,48.6-16.1L177.4,24.35
|
|
||||||
c2.899,2.367,5.732,4.933,8.5,7.7C189.367,35.583,192.55,39.233,195.45,43z"/>
|
|
||||||
</g>
|
|
||||||
<g id="Layer_4">
|
|
||||||
<defs>
|
|
||||||
<path id="SVGID_1_" d="M159.8,110c0-16.733,4.417-31.6,13.25-44.6l22.4-22.4c-2.9-3.767-6.083-7.417-9.55-10.95
|
|
||||||
c-2.768-2.767-5.601-5.333-8.5-7.7L158.1,43.6c-13.934,10.733-30.133,16.1-48.6,16.1c-17.933,0-33.8-5.117-47.6-15.35L41.55,24
|
|
||||||
c-3.066,2.5-6.066,5.183-9,8.05c-3.333,3.333-6.417,6.8-9.25,10.4l21.05,21c9.733,13.533,14.6,29.05,14.6,46.55
|
|
||||||
c0,17.934-5.034,33.884-15.1,47.85l-19.15,19.2c2.433,2.934,5.05,5.8,7.85,8.601c3.367,3.466,6.934,6.633,10.7,9.5L61.8,176.55
|
|
||||||
c13.867-10.2,29.767-15.3,47.7-15.3c18.467,0,34.666,5.366,48.6,16.1L175.65,194.9c2.732-2.134,5.366-4.45,7.899-6.95
|
|
||||||
c0.866-0.7,1.65-1.467,2.351-2.3c2.899-2.934,5.6-5.934,8.1-9l-19-18.95C164.867,143.833,159.8,127.934,159.8,110z"/>
|
|
||||||
</defs>
|
|
||||||
<clipPath id="SVGID_2_">
|
|
||||||
<use xlink:href="#SVGID_1_" overflow="visible"/>
|
|
||||||
</clipPath>
|
|
||||||
<g clip-path="url(#SVGID_2_)">
|
|
||||||
|
|
||||||
<use xlink:href="#hex_grid" width="228.55" height="197.233" x="-114.25" y="-98.617" transform="matrix(1.1415 0 0 -1.1415 105.5 107.75)" overflow="visible"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g id="Layer_2">
|
|
||||||
<g>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#35C6F4" d="M79.1,110.95c-0.033-0.667-0.05-1.333-0.05-2
|
|
||||||
c0-0.7,0.017-1.366,0.05-2c0-0.067,0.017-0.134,0.05-0.2c0.434-7.367,3.333-13.733,8.7-19.1c5.9-5.833,12.983-8.75,21.25-8.75
|
|
||||||
c8.301,0,15.384,2.917,21.25,8.75c5.834,5.934,8.75,13.033,8.75,21.3c0,8.267-2.916,15.35-8.75,21.25
|
|
||||||
c-0.199,0.233-0.416,0.45-0.649,0.649c-0.967,0.934-1.983,1.784-3.05,2.551c-5.066,3.733-10.917,5.6-17.551,5.6
|
|
||||||
c-6.633,0-12.466-1.866-17.5-5.6c-1.333-0.934-2.583-2-3.75-3.2c-4.533-4.5-7.317-9.733-8.35-15.7
|
|
||||||
C79.3,113.334,79.167,112.15,79.1,110.95z M126.1,127.25l3.601,3.6L126.1,127.25z"/>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="none" stroke="#35C6F4" stroke-width="2" stroke-miterlimit="1" d="
|
|
||||||
M158.6,60.25l-15,14.65 M31.7,33.1l40.75,40.65 M126.1,127.25l3.601,3.6 M157.05,158l27.65,28.6 M153.05,153.95l-10.75-11.2
|
|
||||||
M186.6,33l-28,27.25 M33.15,186.25l27.35-27.4"/>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="none" stroke="#35C6F4" stroke-width="7" stroke-miterlimit="1" d="
|
|
||||||
M158.6,60.25l-16.949,17.2 M59.4,61.35L76.6,78.5 M60.5,158.85l16.75-17.399 M153.05,153.95l4,4.05 M139.45,140.4l13.6,13.55"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 26 KiB |
BIN
Logo/Thumbs.db
Normal file
38
appveyor.yml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
version: '0.2.0.{build}'
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- develop
|
||||||
|
|
||||||
|
assembly_info:
|
||||||
|
patch: true
|
||||||
|
file: 'src\NzbDrone.Common\Properties\SharedAssemblyInfo.cs'
|
||||||
|
assembly_version: '{version}'
|
||||||
|
assembly_file_version: '{version}'
|
||||||
|
assembly_informational_version: '{version}-rc1'
|
||||||
|
|
||||||
|
environment:
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
|
|
||||||
|
install:
|
||||||
|
- git submodule update --init --recursive
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- ps: ./build-appveyor.ps1
|
||||||
|
|
||||||
|
test: off
|
||||||
|
# test:
|
||||||
|
# assemblies:
|
||||||
|
# - '_tests\*Test.dll'
|
||||||
|
# categories:
|
||||||
|
# except:
|
||||||
|
# - IntegrationTest
|
||||||
|
# - AutomationTest
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
- path: '_artifacts\*.zip'
|
||||||
|
- path: '_artifacts\*.tar.gz'
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- '%USERPROFILE%\.nuget\packages'
|
||||||
|
- node_modules
|
303
build-appveyor.cake
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
#addin "Cake.Npm"
|
||||||
|
#addin "SharpZipLib"
|
||||||
|
#addin "Cake.Compression"
|
||||||
|
|
||||||
|
// Build variables
|
||||||
|
var outputFolder = "./_output";
|
||||||
|
var outputFolderMono = outputFolder + "_mono";
|
||||||
|
var outputFolderOsx = outputFolder + "_osx";
|
||||||
|
var outputFolderOsxApp = outputFolderOsx + "_app";
|
||||||
|
var testPackageFolder = "./_tests";
|
||||||
|
var testSearchPattern = "*.Test/bin/x86/Release";
|
||||||
|
var sourceFolder = "./src";
|
||||||
|
var solutionFile = sourceFolder + "/NzbDrone.sln";
|
||||||
|
var updateFolder = outputFolder + "/NzbDrone.Update";
|
||||||
|
var updateFolderMono = outputFolderMono + "/NzbDrone.Update";
|
||||||
|
|
||||||
|
// Artifact variables
|
||||||
|
var artifactsFolder = "./_artifacts";
|
||||||
|
var artifactsFolderWindows = artifactsFolder + "/windows";
|
||||||
|
var artifactsFolderLinux = artifactsFolder + "/linux";
|
||||||
|
var artifactsFolderOsx = artifactsFolder + "/osx";
|
||||||
|
var artifactsFolderOsxApp = artifactsFolder + "/osx-app";
|
||||||
|
|
||||||
|
// Utility methods
|
||||||
|
public void RemoveEmptyFolders(string startLocation) {
|
||||||
|
foreach (var directory in System.IO.Directory.GetDirectories(startLocation))
|
||||||
|
{
|
||||||
|
RemoveEmptyFolders(directory);
|
||||||
|
|
||||||
|
if (System.IO.Directory.GetFiles(directory).Length == 0 &&
|
||||||
|
System.IO.Directory.GetDirectories(directory).Length == 0)
|
||||||
|
{
|
||||||
|
DeleteDirectory(directory, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CleanFolder(string path, bool keepConfigFiles) {
|
||||||
|
DeleteFiles(path + "/**/*.transform");
|
||||||
|
|
||||||
|
if (!keepConfigFiles) {
|
||||||
|
DeleteFiles(path + "/**/*.dll.config");
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteFiles(path + "/**/FluentValidation.resources.dll");
|
||||||
|
DeleteFiles(path + "/**/App.config");
|
||||||
|
|
||||||
|
DeleteFiles(path + "/**/*.less");
|
||||||
|
|
||||||
|
DeleteFiles(path + "/**/*.vshost.exe");
|
||||||
|
|
||||||
|
DeleteFiles(path + "/**/*.dylib");
|
||||||
|
|
||||||
|
RemoveEmptyFolders(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateMdbs(string path) {
|
||||||
|
foreach (var file in System.IO.Directory.EnumerateFiles(path, "*.pdb", System.IO.SearchOption.AllDirectories)) {
|
||||||
|
var actualFile = file.Substring(0, file.Length - 4);
|
||||||
|
|
||||||
|
if (FileExists(actualFile + ".exe")) {
|
||||||
|
StartProcess("./tools/pdb2mdb/pdb2mdb.exe", new ProcessSettings()
|
||||||
|
.WithArguments(args => args.Append(actualFile + ".exe")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileExists(actualFile + ".dll")) {
|
||||||
|
StartProcess("./tools/pdb2mdb/pdb2mdb.exe", new ProcessSettings()
|
||||||
|
.WithArguments(args => args.Append(actualFile + ".dll")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build Tasks
|
||||||
|
Task("Compile").Does(() => {
|
||||||
|
// Build
|
||||||
|
if (DirectoryExists(outputFolder)) {
|
||||||
|
DeleteDirectory(outputFolder, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
MSBuild(solutionFile, config =>
|
||||||
|
config.UseToolVersion(MSBuildToolVersion.VS2015)
|
||||||
|
.WithTarget("Clean")
|
||||||
|
.SetVerbosity(Verbosity.Minimal));
|
||||||
|
|
||||||
|
NuGetRestore(solutionFile);
|
||||||
|
|
||||||
|
MSBuild(solutionFile, config =>
|
||||||
|
config.UseToolVersion(MSBuildToolVersion.VS2015)
|
||||||
|
.SetPlatformTarget(PlatformTarget.x86)
|
||||||
|
.SetConfiguration("Release")
|
||||||
|
.WithProperty("AllowedReferenceRelatedFileExtensions", new string[] { ".pdb" })
|
||||||
|
.WithTarget("Build")
|
||||||
|
.SetVerbosity(Verbosity.Minimal));
|
||||||
|
|
||||||
|
CleanFolder(outputFolder, false);
|
||||||
|
|
||||||
|
// Add JsonNet
|
||||||
|
DeleteFiles(outputFolder + "/Newtonsoft.Json.*");
|
||||||
|
CopyFiles(sourceFolder + "/packages/Newtonsoft.Json.*/lib/net35/*.dll", outputFolder);
|
||||||
|
CopyFiles(sourceFolder + "/packages/Newtonsoft.Json.*/lib/net35/*.dll", updateFolder);
|
||||||
|
|
||||||
|
// Remove Mono stuff
|
||||||
|
DeleteFile(outputFolder + "/Mono.Posix.dll");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("Gulp").Does(() => {
|
||||||
|
Npm
|
||||||
|
.WithLogLevel(NpmLogLevel.Silent)
|
||||||
|
.FromPath(".")
|
||||||
|
.Install()
|
||||||
|
.RunScript("build");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("PackageMono").Does(() => {
|
||||||
|
// Start mono package
|
||||||
|
if (DirectoryExists(outputFolderMono)) {
|
||||||
|
DeleteDirectory(outputFolderMono, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyDirectory(outputFolder, outputFolderMono);
|
||||||
|
|
||||||
|
// Create MDBs
|
||||||
|
CreateMdbs(outputFolderMono);
|
||||||
|
|
||||||
|
// Remove PDBs
|
||||||
|
DeleteFiles(outputFolderMono + "/**/*.pdb");
|
||||||
|
|
||||||
|
// Remove service helpers
|
||||||
|
DeleteFiles(outputFolderMono + "/ServiceUninstall.*");
|
||||||
|
DeleteFiles(outputFolderMono + "/ServiceInstall.*");
|
||||||
|
|
||||||
|
// Remove native windows binaries
|
||||||
|
DeleteFiles(outputFolderMono + "/sqlite3.*");
|
||||||
|
DeleteFiles(outputFolderMono + "/MediaInfo.*");
|
||||||
|
|
||||||
|
// Adding NzbDrone.Core.dll.config (for dllmap)
|
||||||
|
CopyFile(sourceFolder + "/NzbDrone.Core/NzbDrone.Core.dll.config", outputFolderMono + "/NzbDrone.Core.dll.config");
|
||||||
|
|
||||||
|
// Adding CurlSharp.dll.config (for dllmap)
|
||||||
|
CopyFile(sourceFolder + "/NzbDrone.Common/CurlSharp.dll.config", outputFolderMono + "/CurlSharp.dll.config");
|
||||||
|
|
||||||
|
// Renaming Radarr.Console.exe to Radarr.exe
|
||||||
|
DeleteFiles(outputFolderMono + "/Radarr.exe*");
|
||||||
|
MoveFile(outputFolderMono + "/Radarr.Console.exe", outputFolderMono + "/Radarr.exe");
|
||||||
|
MoveFile(outputFolderMono + "/Radarr.Console.exe.config", outputFolderMono + "/Radarr.exe.config");
|
||||||
|
MoveFile(outputFolderMono + "/Radarr.Console.exe.mdb", outputFolderMono + "/Radarr.exe.mdb");
|
||||||
|
|
||||||
|
// Remove NzbDrone.Windows.*
|
||||||
|
DeleteFiles(outputFolderMono + "/NzbDrone.Windows.*");
|
||||||
|
|
||||||
|
// Adding NzbDrone.Mono to updatePackage
|
||||||
|
CopyFiles(outputFolderMono + "/NzbDrone.Mono.*", updateFolderMono);
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("PackageOsx").Does(() => {
|
||||||
|
// Start osx package
|
||||||
|
if (DirectoryExists(outputFolderOsx)) {
|
||||||
|
DeleteDirectory(outputFolderOsx, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyDirectory(outputFolderMono, outputFolderOsx);
|
||||||
|
|
||||||
|
// Adding sqlite dylibs
|
||||||
|
CopyFiles(sourceFolder + "/Libraries/Sqlite/*.dylib", outputFolderOsx);
|
||||||
|
|
||||||
|
// Adding MediaInfo dylib
|
||||||
|
CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx);
|
||||||
|
|
||||||
|
// Adding Startup script
|
||||||
|
CopyFile("./osx/Sonarr", outputFolderOsx + "/Sonarr");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("PackageOsxApp").Does(() => {
|
||||||
|
// Start osx app package
|
||||||
|
if (DirectoryExists(outputFolderOsxApp)) {
|
||||||
|
DeleteDirectory(outputFolderOsxApp, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateDirectory(outputFolderOsxApp);
|
||||||
|
|
||||||
|
// Copy osx package files
|
||||||
|
CopyDirectory("./osx/Radarr.app", outputFolderOsxApp + "/Radarr.app");
|
||||||
|
CopyDirectory(outputFolderOsx, outputFolderOsxApp + "/Radarr.app/Contents/MacOS");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("PackageTests").Does(() => {
|
||||||
|
// Start tests package
|
||||||
|
if (DirectoryExists(testPackageFolder)) {
|
||||||
|
DeleteDirectory(testPackageFolder, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateDirectory(testPackageFolder);
|
||||||
|
|
||||||
|
// Copy tests
|
||||||
|
CopyFiles(sourceFolder + "/" + testSearchPattern + "/*", testPackageFolder);
|
||||||
|
foreach (var directory in System.IO.Directory.GetDirectories(sourceFolder, "*.Test")) {
|
||||||
|
var releaseDirectory = directory + "/bin/x86/Release";
|
||||||
|
if (DirectoryExists(releaseDirectory)) {
|
||||||
|
foreach (var releaseSubDirectory in System.IO.Directory.GetDirectories(releaseDirectory)) {
|
||||||
|
Information(System.IO.Path.GetDirectoryName(releaseSubDirectory));
|
||||||
|
CopyDirectory(releaseSubDirectory, testPackageFolder + "/" + System.IO.Path.GetFileName(releaseSubDirectory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install NUnit.ConsoleRunner
|
||||||
|
NuGetInstall("NUnit.ConsoleRunner", new NuGetInstallSettings {
|
||||||
|
Version = "3.2.0",
|
||||||
|
OutputDirectory = testPackageFolder
|
||||||
|
});
|
||||||
|
|
||||||
|
// Copy dlls
|
||||||
|
CopyFiles(outputFolder + "/*.dll", testPackageFolder);
|
||||||
|
|
||||||
|
// Copy scripts
|
||||||
|
CopyFiles("./*.sh", testPackageFolder);
|
||||||
|
|
||||||
|
// Create MDBs for tests
|
||||||
|
CreateMdbs(testPackageFolder);
|
||||||
|
|
||||||
|
// Remove config
|
||||||
|
DeleteFiles(testPackageFolder + "/*.log.config");
|
||||||
|
|
||||||
|
// Clean
|
||||||
|
CleanFolder(testPackageFolder, true);
|
||||||
|
|
||||||
|
// Adding NzbDrone.Core.dll.config (for dllmap)
|
||||||
|
CopyFile(sourceFolder + "/NzbDrone.Core/NzbDrone.Core.dll.config", testPackageFolder + "/NzbDrone.Core.dll.config");
|
||||||
|
|
||||||
|
// Adding CurlSharp.dll.config (for dllmap)
|
||||||
|
CopyFile(sourceFolder + "/NzbDrone.Common/CurlSharp.dll.config", testPackageFolder + "/CurlSharp.dll.config");
|
||||||
|
|
||||||
|
// Adding CurlSharp libraries
|
||||||
|
CopyFiles(sourceFolder + "/ExternalModules/CurlSharp/libs/i386/*", testPackageFolder);
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("CleanupWindowsPackage").Does(() => {
|
||||||
|
// Remove mono
|
||||||
|
DeleteFiles(outputFolder + "/NzbDrone.Mono.*");
|
||||||
|
|
||||||
|
// Adding NzbDrone.Windows to updatePackage
|
||||||
|
CopyFiles(outputFolder + "/NzbDrone.Windows.*", updateFolder);
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("Build")
|
||||||
|
.IsDependentOn("Compile")
|
||||||
|
.IsDependentOn("Gulp")
|
||||||
|
.IsDependentOn("PackageMono")
|
||||||
|
.IsDependentOn("PackageOsx")
|
||||||
|
.IsDependentOn("PackageOsxApp")
|
||||||
|
.IsDependentOn("PackageTests")
|
||||||
|
.IsDependentOn("CleanupWindowsPackage");
|
||||||
|
|
||||||
|
// Build Artifacts
|
||||||
|
Task("CleanArtifacts").Does(() => {
|
||||||
|
if (DirectoryExists(artifactsFolder)) {
|
||||||
|
DeleteDirectory(artifactsFolder, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateDirectory(artifactsFolder);
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("ArtifactsWindows").Does(() => {
|
||||||
|
CopyDirectory(outputFolder, artifactsFolderWindows + "/Radarr");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("ArtifactsLinux").Does(() => {
|
||||||
|
CopyDirectory(outputFolderMono, artifactsFolderLinux + "/Radarr");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("ArtifactsOsx").Does(() => {
|
||||||
|
CopyDirectory(outputFolderOsx, artifactsFolderOsx + "/Radarr");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("ArtifactsOsxApp").Does(() => {
|
||||||
|
CopyDirectory(outputFolderOsxApp, artifactsFolderOsxApp);
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("CompressArtifacts").Does(() => {
|
||||||
|
var prefix = "";
|
||||||
|
|
||||||
|
if (AppVeyor.IsRunningOnAppVeyor) {
|
||||||
|
prefix += AppVeyor.Environment.Repository.Branch + ".";
|
||||||
|
prefix += AppVeyor.Environment.Build.Version + ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
Zip(artifactsFolderWindows, artifactsFolder + "/Radarr." + prefix + "windows.zip");
|
||||||
|
GZipCompress(artifactsFolderLinux, artifactsFolder + "/Radarr." + prefix + "linux.tar.gz");
|
||||||
|
GZipCompress(artifactsFolderOsx, artifactsFolder + "/Radarr." + prefix + "osx.tar.gz");
|
||||||
|
Zip(artifactsFolderOsxApp, artifactsFolder + "/Radarr." + prefix + "osx-app.zip");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("Artifacts")
|
||||||
|
.IsDependentOn("CleanArtifacts")
|
||||||
|
.IsDependentOn("ArtifactsWindows")
|
||||||
|
.IsDependentOn("ArtifactsLinux")
|
||||||
|
.IsDependentOn("ArtifactsOsx")
|
||||||
|
.IsDependentOn("ArtifactsOsxApp")
|
||||||
|
.IsDependentOn("CompressArtifacts");
|
||||||
|
|
||||||
|
// Run
|
||||||
|
RunTarget("Build");
|
||||||
|
RunTarget("Artifacts");
|
184
build-appveyor.ps1
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
##########################################################################
|
||||||
|
# This is the Cake bootstrapper script for PowerShell.
|
||||||
|
# This file was downloaded from https://github.com/cake-build/resources
|
||||||
|
# Feel free to change this file to fit your needs.
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
This is a Powershell script to bootstrap a Cake build.
|
||||||
|
.DESCRIPTION
|
||||||
|
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
|
||||||
|
and execute your Cake build script with the parameters you provide.
|
||||||
|
.PARAMETER Script
|
||||||
|
The build script to execute.
|
||||||
|
.PARAMETER Target
|
||||||
|
The build script target to run.
|
||||||
|
.PARAMETER Configuration
|
||||||
|
The build configuration to use.
|
||||||
|
.PARAMETER Verbosity
|
||||||
|
Specifies the amount of information to be displayed.
|
||||||
|
.PARAMETER Experimental
|
||||||
|
Tells Cake to use the latest Roslyn release.
|
||||||
|
.PARAMETER WhatIf
|
||||||
|
Performs a dry run of the build script.
|
||||||
|
No tasks will be executed.
|
||||||
|
.PARAMETER Mono
|
||||||
|
Tells Cake to use the Mono scripting engine.
|
||||||
|
.PARAMETER SkipToolPackageRestore
|
||||||
|
Skips restoring of packages.
|
||||||
|
.PARAMETER ScriptArgs
|
||||||
|
Remaining arguments are added here.
|
||||||
|
.LINK
|
||||||
|
http://cakebuild.net
|
||||||
|
#>
|
||||||
|
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
[string]$Script = "build-appveyor.cake",
|
||||||
|
[string]$Target = "Default",
|
||||||
|
[ValidateSet("Release", "Debug")]
|
||||||
|
[string]$Configuration = "Release",
|
||||||
|
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
|
||||||
|
[string]$Verbosity = "Verbose",
|
||||||
|
[switch]$Experimental,
|
||||||
|
[Alias("DryRun","Noop")]
|
||||||
|
[switch]$WhatIf,
|
||||||
|
[switch]$Mono,
|
||||||
|
[switch]$SkipToolPackageRestore,
|
||||||
|
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
|
||||||
|
[string[]]$ScriptArgs
|
||||||
|
)
|
||||||
|
|
||||||
|
[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
|
||||||
|
function MD5HashFile([string] $filePath)
|
||||||
|
{
|
||||||
|
if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
|
||||||
|
{
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.IO.Stream] $file = $null;
|
||||||
|
[System.Security.Cryptography.MD5] $md5 = $null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$md5 = [System.Security.Cryptography.MD5]::Create()
|
||||||
|
$file = [System.IO.File]::OpenRead($filePath)
|
||||||
|
return [System.BitConverter]::ToString($md5.ComputeHash($file))
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if ($file -ne $null)
|
||||||
|
{
|
||||||
|
$file.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Preparing to run build script..."
|
||||||
|
|
||||||
|
if(!$PSScriptRoot){
|
||||||
|
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||||
|
}
|
||||||
|
|
||||||
|
$TOOLS_DIR = Join-Path $PSScriptRoot "tools-cake"
|
||||||
|
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
|
||||||
|
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
|
||||||
|
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
||||||
|
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
|
||||||
|
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
|
||||||
|
|
||||||
|
# Should we use mono?
|
||||||
|
$UseMono = "";
|
||||||
|
if($Mono.IsPresent) {
|
||||||
|
Write-Verbose -Message "Using the Mono based scripting engine."
|
||||||
|
$UseMono = "-mono"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Should we use the new Roslyn?
|
||||||
|
$UseExperimental = "";
|
||||||
|
if($Experimental.IsPresent -and !($Mono.IsPresent)) {
|
||||||
|
Write-Verbose -Message "Using experimental version of Roslyn."
|
||||||
|
$UseExperimental = "-experimental"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Is this a dry run?
|
||||||
|
$UseDryRun = "";
|
||||||
|
if($WhatIf.IsPresent) {
|
||||||
|
$UseDryRun = "-dryrun"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure tools folder exists
|
||||||
|
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
|
||||||
|
Write-Verbose -Message "Creating tools directory..."
|
||||||
|
New-Item -Path $TOOLS_DIR -Type directory | out-null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure that packages.config exist.
|
||||||
|
if (!(Test-Path $PACKAGES_CONFIG)) {
|
||||||
|
Write-Verbose -Message "Downloading packages.config..."
|
||||||
|
try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
|
||||||
|
Throw "Could not download packages.config."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try find NuGet.exe in path if not exists
|
||||||
|
if (!(Test-Path $NUGET_EXE)) {
|
||||||
|
Write-Verbose -Message "Trying to find nuget.exe in PATH..."
|
||||||
|
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
|
||||||
|
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
|
||||||
|
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
|
||||||
|
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
|
||||||
|
$NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try download NuGet.exe if not exists
|
||||||
|
if (!(Test-Path $NUGET_EXE)) {
|
||||||
|
Write-Verbose -Message "Downloading NuGet.exe..."
|
||||||
|
try {
|
||||||
|
(New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
|
||||||
|
} catch {
|
||||||
|
Throw "Could not download NuGet.exe."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Save nuget.exe path to environment to be available to child processed
|
||||||
|
$ENV:NUGET_EXE = $NUGET_EXE
|
||||||
|
|
||||||
|
# Restore tools from NuGet?
|
||||||
|
if(-Not $SkipToolPackageRestore.IsPresent) {
|
||||||
|
Push-Location
|
||||||
|
Set-Location $TOOLS_DIR
|
||||||
|
|
||||||
|
# Check for changes in packages.config and remove installed tools if true.
|
||||||
|
[string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
|
||||||
|
if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
|
||||||
|
($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
|
||||||
|
Write-Verbose -Message "Missing or changed package.config hash..."
|
||||||
|
Remove-Item * -Recurse -Exclude packages.config,nuget.exe
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose -Message "Restoring tools from NuGet..."
|
||||||
|
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Throw "An error occured while restoring NuGet tools."
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
|
||||||
|
}
|
||||||
|
Write-Verbose -Message ($NuGetOutput | out-string)
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure that Cake has been installed.
|
||||||
|
if (!(Test-Path $CAKE_EXE)) {
|
||||||
|
Throw "Could not find Cake.exe at $CAKE_EXE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start Cake
|
||||||
|
Write-Host "Running build script..."
|
||||||
|
Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
|
||||||
|
exit $LASTEXITCODE
|
8
build.sh
|
@ -154,8 +154,8 @@ PackageMono()
|
||||||
cp $sourceFolder/NzbDrone.Common/CurlSharp.dll.config $outputFolderMono
|
cp $sourceFolder/NzbDrone.Common/CurlSharp.dll.config $outputFolderMono
|
||||||
|
|
||||||
echo "Renaming NzbDrone.Console.exe to NzbDrone.exe"
|
echo "Renaming NzbDrone.Console.exe to NzbDrone.exe"
|
||||||
rm $outputFolderMono/NzbDrone.exe*
|
rm $outputFolderMono/Radarr.exe*
|
||||||
for file in $outputFolderMono/NzbDrone.Console.exe*; do
|
for file in $outputFolderMono/Radarr.Console.exe*; do
|
||||||
mv "$file" "${file//.Console/}"
|
mv "$file" "${file//.Console/}"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -192,8 +192,8 @@ PackageOsxApp()
|
||||||
rm -rf $outputFolderOsxApp
|
rm -rf $outputFolderOsxApp
|
||||||
mkdir $outputFolderOsxApp
|
mkdir $outputFolderOsxApp
|
||||||
|
|
||||||
cp -r ./osx/Sonarr.app $outputFolderOsxApp
|
cp -r ./osx/Radarr.app $outputFolderOsxApp
|
||||||
cp -r $outputFolderOsx $outputFolderOsxApp/Sonarr.app/Contents/MacOS
|
cp -r $outputFolderOsx $outputFolderOsxApp/Radarr.app/Contents/MacOS
|
||||||
|
|
||||||
echo "##teamcity[progressFinish 'Creating OS X App Package']"
|
echo "##teamcity[progressFinish 'Creating OS X App Package']"
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,16 @@ gulp.task('less', function() {
|
||||||
paths.src.root + 'Series/series.less',
|
paths.src.root + 'Series/series.less',
|
||||||
paths.src.root + 'Activity/activity.less',
|
paths.src.root + 'Activity/activity.less',
|
||||||
paths.src.root + 'AddSeries/addSeries.less',
|
paths.src.root + 'AddSeries/addSeries.less',
|
||||||
|
paths.src.root + 'AddMovies/addMovies.less',
|
||||||
paths.src.root + 'Calendar/calendar.less',
|
paths.src.root + 'Calendar/calendar.less',
|
||||||
paths.src.root + 'Cells/cells.less',
|
paths.src.root + 'Cells/cells.less',
|
||||||
paths.src.root + 'ManualImport/manualimport.less',
|
paths.src.root + 'ManualImport/manualimport.less',
|
||||||
paths.src.root + 'Settings/settings.less',
|
paths.src.root + 'Settings/settings.less',
|
||||||
paths.src.root + 'System/Logs/logs.less',
|
paths.src.root + 'System/Logs/logs.less',
|
||||||
paths.src.root + 'System/Update/update.less',
|
paths.src.root + 'System/Update/update.less',
|
||||||
paths.src.root + 'System/Info/info.less'
|
paths.src.root + 'System/Info/info.less',
|
||||||
|
paths.src.root + 'Movies/movies.less',
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return gulp.src(src)
|
return gulp.src(src)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>Sonarr</string>
|
<string>Sonarr</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>sonarr.icns</string>
|
<string>radarr.icns</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>com.osx.sonarr.tv</string>
|
<string>com.osx.sonarr.tv</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
BIN
osx/Radarr.app/Contents/Resources/radarr.icns
Normal file
16
osx/Sonarr
|
@ -4,9 +4,9 @@
|
||||||
DIR=$(cd "$(dirname "$0")"; pwd)
|
DIR=$(cd "$(dirname "$0")"; pwd)
|
||||||
|
|
||||||
#change these values to match your app
|
#change these values to match your app
|
||||||
EXE_PATH="$DIR/NzbDrone.exe"
|
EXE_PATH="$DIR/Radarr.exe"
|
||||||
APPNAME="Sonarr"
|
APPNAME="Sonarr"
|
||||||
|
|
||||||
#set up environment
|
#set up environment
|
||||||
if [[ -x '/opt/local/bin/mono' ]]; then
|
if [[ -x '/opt/local/bin/mono' ]]; then
|
||||||
export PATH="/opt/local/bin:$PATH"
|
export PATH="/opt/local/bin:$PATH"
|
||||||
|
@ -29,11 +29,11 @@ export DYLD_FALLBACK_LIBRARY_PATH="$DYLD_FALLBACK_LIBRARY_PATH:$HOME/lib:/usr/lo
|
||||||
#mono version check
|
#mono version check
|
||||||
REQUIRED_MAJOR=3
|
REQUIRED_MAJOR=3
|
||||||
REQUIRED_MINOR=10
|
REQUIRED_MINOR=10
|
||||||
|
|
||||||
VERSION_TITLE="Cannot launch $APPNAME"
|
VERSION_TITLE="Cannot launch $APPNAME"
|
||||||
VERSION_MSG="$APPNAME requires Mono Runtime Environment(MRE) $REQUIRED_MAJOR.$REQUIRED_MINOR or later."
|
VERSION_MSG="$APPNAME requires Mono Runtime Environment(MRE) $REQUIRED_MAJOR.$REQUIRED_MINOR or later."
|
||||||
DOWNLOAD_URL="http://www.mono-project.com/download/#download-mac"
|
DOWNLOAD_URL="http://www.mono-project.com/download/#download-mac"
|
||||||
|
|
||||||
MONO_VERSION="$(mono --version | grep 'Mono JIT compiler version ' | cut -f5 -d\ )"
|
MONO_VERSION="$(mono --version | grep 'Mono JIT compiler version ' | cut -f5 -d\ )"
|
||||||
# if [[ -o DEBUG ]]; then osascript -e "display dialog \"MONO_VERSION: $MONO_VERSION\""; fi
|
# if [[ -o DEBUG ]]; then osascript -e "display dialog \"MONO_VERSION: $MONO_VERSION\""; fi
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ MONO_VERSION_MAJOR="$(echo $MONO_VERSION | cut -f1 -d.)"
|
||||||
MONO_VERSION_MINOR="$(echo $MONO_VERSION | cut -f2 -d.)"
|
MONO_VERSION_MINOR="$(echo $MONO_VERSION | cut -f2 -d.)"
|
||||||
if [ -z "$MONO_VERSION" ] \
|
if [ -z "$MONO_VERSION" ] \
|
||||||
|| [ $MONO_VERSION_MAJOR -lt $REQUIRED_MAJOR ] \
|
|| [ $MONO_VERSION_MAJOR -lt $REQUIRED_MAJOR ] \
|
||||||
|| [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ]
|
|| [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ]
|
||||||
then
|
then
|
||||||
osascript \
|
osascript \
|
||||||
-e "set question to display dialog \"$VERSION_MSG\" with title \"$VERSION_TITLE\" buttons {\"Cancel\", \"Download...\"} default button 2" \
|
-e "set question to display dialog \"$VERSION_MSG\" with title \"$VERSION_TITLE\" buttons {\"Cancel\", \"Download...\"} default button 2" \
|
||||||
|
@ -51,8 +51,8 @@ then
|
||||||
echo "$VERSION_MSG"
|
echo "$VERSION_MSG"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MONO_EXEC="exec mono --debug"
|
MONO_EXEC="exec mono --debug"
|
||||||
|
|
||||||
#run app using mono
|
#run app using mono
|
||||||
$MONO_EXEC "$EXE_PATH"
|
$MONO_EXEC "$EXE_PATH"
|
||||||
|
|
68
package.sh
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
if [ "$TRAVIS_PULL_REQUEST" != false ]; then
|
||||||
|
echo "Need to supply version argument" && exit;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use mono or .net depending on OS
|
||||||
|
case "$(uname -s)" in
|
||||||
|
CYGWIN*|MINGW32*|MINGW64*|MSYS*)
|
||||||
|
# on windows, use dotnet
|
||||||
|
runtime="dotnet"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# otherwise use mono
|
||||||
|
runtime="mono"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
|
||||||
|
VERSION="`date +%H:%M:%S`"
|
||||||
|
YEAR="`date +%Y`"
|
||||||
|
MONTH="`date +%m`"
|
||||||
|
DAY="`date +%d`"
|
||||||
|
else
|
||||||
|
VERSION=$1
|
||||||
|
fi
|
||||||
|
outputFolder='./_output'
|
||||||
|
outputFolderMono='./_output_mono'
|
||||||
|
outputFolderOsx='./_output_osx'
|
||||||
|
outputFolderOsxApp='./_output_osx_app'
|
||||||
|
|
||||||
|
tr -d "\r" < $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr > $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
|
||||||
|
rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr
|
||||||
|
chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
|
||||||
|
mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr >& error.log
|
||||||
|
|
||||||
|
cp -r $outputFolder/ Radarr_Windows_$VERSION
|
||||||
|
cp -r $outputFolderMono/ Radarr_Mono_$VERSION
|
||||||
|
cp -r $outputFolderOsxApp/ Radarr_OSX_$VERSION
|
||||||
|
|
||||||
|
if [ $runtime = "dotnet" ] ; then
|
||||||
|
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
|
||||||
|
./7za.exe a -ttar -so Radarr_Mono_$VERSION.tar ./Radarr_Mono_$VERSION/* | ./7za.exe a -si Radarr_Mono_$VERSION.tar.gz
|
||||||
|
./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz
|
||||||
|
./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz
|
||||||
|
else
|
||||||
|
zip -r Radarr_Windows_$VERSION.zip Radarr_Windows_$VERSION/* >& /dev/null
|
||||||
|
zip -r Radarr_Mono_$VERSION.zip Radarr_Mono_$VERSION/* >& /dev/null #TODO update for tar.gz
|
||||||
|
zip -r Radarr_OSX_$VERSION_App.zip Radarr_OSX_$VERSION/* >& /dev/null
|
||||||
|
fi
|
||||||
|
ftp -n ftp.leonardogalli.ch << END_SCRIPT
|
||||||
|
passive
|
||||||
|
quote USER $FTP_USER
|
||||||
|
quote PASS $FTP_PASS
|
||||||
|
mkdir builds
|
||||||
|
cd builds
|
||||||
|
mkdir $YEAR
|
||||||
|
cd $YEAR
|
||||||
|
mkdir $MONTH
|
||||||
|
cd $MONTH
|
||||||
|
mkdir $DAY
|
||||||
|
cd $DAY
|
||||||
|
binary
|
||||||
|
put Radarr_Windows_$VERSION.zip
|
||||||
|
put Radarr_Mono_$VERSION.zip
|
||||||
|
put Radarr_OSX_$VERSION.zip
|
||||||
|
quit
|
||||||
|
END_SCRIPT
|
49
readme.md
|
@ -1,27 +1,50 @@
|
||||||
# Sonarr #
|
# Radarr
|
||||||
|
|
||||||
|
| Service | Master | Develop |
|
||||||
|
|----------|:---------------------------:|:----------------------------:|
|
||||||
|
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr) |
|
||||||
|
| Travis | [](https://travis-ci.org/galli-leo/Radarr) | [](https://travis-ci.org/galli-leo/Radarr) |
|
||||||
|
|
||||||
Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.
|
This fork of Sonarr aims to turn it into something like Couchpotato.
|
||||||
|
|
||||||
|
## Currently working:
|
||||||
|
* Adding new movies
|
||||||
|
* Manually searching for releases of movies.
|
||||||
|
* Automatically searching for releases.
|
||||||
|
* Automatically importing downloaded movies.
|
||||||
|
* Recognizing Special Editions, Director's Cut, etc.
|
||||||
|
* Identifying releases with hardcoded subs.
|
||||||
|
* Rarbg.to, Torznab and Newznab Indexer.
|
||||||
|
* QBittorrent and Deluge download client (Other clients are coming)
|
||||||
|
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||||
|
|
||||||
|
## Planned Features:
|
||||||
|
* Scanning PreDB to know when a new release is available.
|
||||||
|
* Fixing the other Indexers and download clients.
|
||||||
|
* Importing of Sonarr config.
|
||||||
|
|
||||||
|
## Download
|
||||||
|
The latest precompiled binary versions can be found here: https://github.com/galli-leo/Radarr/releases.
|
||||||
|
|
||||||
|
For more up to date versions (but also sometimes broken), daily builds can be found here:
|
||||||
|
* [OSX](https://leonardogalli.ch/radarr/builds/latest.php?os=osx)
|
||||||
|
* [Windows](https://leonardogalli.ch/radarr/builds/latest.php?os=windows)
|
||||||
|
* [Linux](https://leonardogalli.ch/radarr/builds/latest.php?os=mono)
|
||||||
|
|
||||||
## Major Features Include: ##
|
## Major Features Include: ##
|
||||||
|
|
||||||
* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
|
* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
|
||||||
* Automatically detects new episodes
|
* Can watch for better quality of the movies you have and do an upgrade.
|
||||||
* Can scan your existing library and download any missing episodes
|
|
||||||
* Can watch for better quality of the episodes you already have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
|
|
||||||
* Automatic failed download handling will try another release if one fails
|
* Automatic failed download handling will try another release if one fails
|
||||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically
|
* Manual search so you can pick any release or to see why a release was not downloaded automatically.
|
||||||
* Fully configurable episode renaming
|
* Full integration with SABNzbd and NzbGet.
|
||||||
* Full integration with SABNzbd and NzbGet
|
* Full integration with XBMC, Plex (notification, library update, metadata).
|
||||||
* Full integration with XBMC, Plex (notification, library update, metadata)
|
|
||||||
* Full support for specials and multi-episode releases
|
|
||||||
* And a beautiful UI
|
* And a beautiful UI
|
||||||
|
|
||||||
|
|
||||||
## Configuring Development Environment: ##
|
## Configuring Development Environment: ##
|
||||||
|
|
||||||
### Requirements ###
|
### Requirements ###
|
||||||
- Visual Studio 2015 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
|
- Visual Studio 2015 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) or Mono
|
||||||
- [Git](http://git-scm.com/downloads)
|
- [Git](http://git-scm.com/downloads)
|
||||||
- [NodeJS](http://nodejs.org/download/)
|
- [NodeJS](http://nodejs.org/download/)
|
||||||
|
|
||||||
|
@ -37,7 +60,7 @@ Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS fee
|
||||||
|
|
||||||
|
|
||||||
### Development ###
|
### Development ###
|
||||||
- Open `NzbDrone.sln` in Visual Studio
|
- Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed.
|
||||||
- Make sure `NzbDrone.Console` is set as the startup project
|
- Make sure `NzbDrone.Console` is set as the startup project
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
sonarr.icns
Normal file
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.0.0.*")]
|
[assembly: AssemblyVersion("0.1.0.*")]
|
||||||
|
|
|
@ -21,4 +21,3 @@ using System.Runtime.InteropServices;
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("260b2ff9-d3b7-4d8a-b720-a12c93d045e5")]
|
[assembly: Guid("260b2ff9-d3b7-4d8a-b720-a12c93d045e5")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.0.0.*")]
|
|
||||||
|
|
|
@ -39,6 +39,8 @@ namespace NzbDrone.Api.Config
|
||||||
SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat();
|
SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat();
|
||||||
SharedValidator.RuleFor(c => c.SeriesFolderFormat).ValidSeriesFolderFormat();
|
SharedValidator.RuleFor(c => c.SeriesFolderFormat).ValidSeriesFolderFormat();
|
||||||
SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat();
|
SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat();
|
||||||
|
SharedValidator.RuleFor(c => c.StandardMovieFormat).ValidMovieFormat();
|
||||||
|
SharedValidator.RuleFor(c => c.MovieFolderFormat).ValidMovieFolderFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateNamingConfig(NamingConfigResource resource)
|
private void UpdateNamingConfig(NamingConfigResource resource)
|
||||||
|
@ -54,7 +56,13 @@ namespace NzbDrone.Api.Config
|
||||||
var nameSpec = _namingConfigService.GetConfig();
|
var nameSpec = _namingConfigService.GetConfig();
|
||||||
var resource = nameSpec.ToResource();
|
var resource = nameSpec.ToResource();
|
||||||
|
|
||||||
if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace())
|
//if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace())
|
||||||
|
//{
|
||||||
|
// var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
|
||||||
|
// basicConfig.AddToResource(resource);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (resource.StandardMovieFormat.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
|
var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
|
||||||
basicConfig.AddToResource(resource);
|
basicConfig.AddToResource(resource);
|
||||||
|
@ -73,39 +81,50 @@ namespace NzbDrone.Api.Config
|
||||||
var nameSpec = config.ToModel();
|
var nameSpec = config.ToModel();
|
||||||
var sampleResource = new NamingSampleResource();
|
var sampleResource = new NamingSampleResource();
|
||||||
|
|
||||||
var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec);
|
//var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec);
|
||||||
var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec);
|
//var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec);
|
||||||
var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec);
|
//var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec);
|
||||||
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
//var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
||||||
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
//var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
||||||
|
|
||||||
sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
|
var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
|
||||||
? "Invalid format"
|
|
||||||
: singleEpisodeSampleResult.FileName;
|
|
||||||
|
|
||||||
sampleResource.MultiEpisodeExample = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult) != null
|
//sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
|
||||||
? "Invalid format"
|
// ? "Invalid format"
|
||||||
: multiEpisodeSampleResult.FileName;
|
// : singleEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
sampleResource.DailyEpisodeExample = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult) != null
|
//sampleResource.MultiEpisodeExample = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult) != null
|
||||||
? "Invalid format"
|
// ? "Invalid format"
|
||||||
: dailyEpisodeSampleResult.FileName;
|
// : multiEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
sampleResource.AnimeEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult) != null
|
//sampleResource.DailyEpisodeExample = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult) != null
|
||||||
? "Invalid format"
|
// ? "Invalid format"
|
||||||
: animeEpisodeSampleResult.FileName;
|
// : dailyEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
|
//sampleResource.AnimeEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult) != null
|
||||||
? "Invalid format"
|
// ? "Invalid format"
|
||||||
: animeMultiEpisodeSampleResult.FileName;
|
// : animeEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
|
//sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
|
||||||
|
// ? "Invalid format"
|
||||||
|
// : animeMultiEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
|
sampleResource.MovieExample = nameSpec.StandardMovieFormat.IsNullOrWhiteSpace()
|
||||||
|
? "Invalid Format"
|
||||||
|
: movieSampleResult.FileName;
|
||||||
|
|
||||||
|
//sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
|
||||||
|
// ? "Invalid format"
|
||||||
|
// : _filenameSampleService.GetSeriesFolderSample(nameSpec);
|
||||||
|
|
||||||
|
//sampleResource.SeasonFolderExample = nameSpec.SeasonFolderFormat.IsNullOrWhiteSpace()
|
||||||
|
// ? "Invalid format"
|
||||||
|
// : _filenameSampleService.GetSeasonFolderSample(nameSpec);
|
||||||
|
|
||||||
|
sampleResource.MovieFolderExample = nameSpec.MovieFolderFormat.IsNullOrWhiteSpace()
|
||||||
? "Invalid format"
|
? "Invalid format"
|
||||||
: _filenameSampleService.GetSeriesFolderSample(nameSpec);
|
: _filenameSampleService.GetMovieFolderSample(nameSpec);
|
||||||
|
|
||||||
sampleResource.SeasonFolderExample = nameSpec.SeasonFolderFormat.IsNullOrWhiteSpace()
|
|
||||||
? "Invalid format"
|
|
||||||
: _filenameSampleService.GetSeasonFolderSample(nameSpec);
|
|
||||||
|
|
||||||
return sampleResource.AsResponse();
|
return sampleResource.AsResponse();
|
||||||
}
|
}
|
||||||
|
@ -118,19 +137,25 @@ namespace NzbDrone.Api.Config
|
||||||
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
||||||
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
||||||
|
|
||||||
|
var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
|
||||||
|
|
||||||
var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult);
|
var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult);
|
||||||
var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult);
|
var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult);
|
||||||
var dailyEpisodeValidationResult = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult);
|
var dailyEpisodeValidationResult = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult);
|
||||||
var animeEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult);
|
var animeEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult);
|
||||||
var animeMultiEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult);
|
var animeMultiEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult);
|
||||||
|
|
||||||
|
//var standardMovieValidationResult = _filenameValidationService.ValidateMovieFilename(movieSampleResult); For now, let's hope the user is not stupid enough :/
|
||||||
|
|
||||||
var validationFailures = new List<ValidationFailure>();
|
var validationFailures = new List<ValidationFailure>();
|
||||||
|
|
||||||
validationFailures.AddIfNotNull(singleEpisodeValidationResult);
|
//validationFailures.AddIfNotNull(singleEpisodeValidationResult);
|
||||||
validationFailures.AddIfNotNull(multiEpisodeValidationResult);
|
//validationFailures.AddIfNotNull(multiEpisodeValidationResult);
|
||||||
validationFailures.AddIfNotNull(dailyEpisodeValidationResult);
|
//validationFailures.AddIfNotNull(dailyEpisodeValidationResult);
|
||||||
validationFailures.AddIfNotNull(animeEpisodeValidationResult);
|
//validationFailures.AddIfNotNull(animeEpisodeValidationResult);
|
||||||
validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
|
//validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
|
||||||
|
|
||||||
|
//validationFailures.AddIfNotNull(standardMovieValidationResult);
|
||||||
|
|
||||||
if (validationFailures.Any())
|
if (validationFailures.Any())
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,8 @@ namespace NzbDrone.Api.Config
|
||||||
{
|
{
|
||||||
public bool RenameEpisodes { get; set; }
|
public bool RenameEpisodes { get; set; }
|
||||||
public bool ReplaceIllegalCharacters { get; set; }
|
public bool ReplaceIllegalCharacters { get; set; }
|
||||||
|
public string StandardMovieFormat { get; set; }
|
||||||
|
public string MovieFolderFormat { get; set; }
|
||||||
public int MultiEpisodeStyle { get; set; }
|
public int MultiEpisodeStyle { get; set; }
|
||||||
public string StandardEpisodeFormat { get; set; }
|
public string StandardEpisodeFormat { get; set; }
|
||||||
public string DailyEpisodeFormat { get; set; }
|
public string DailyEpisodeFormat { get; set; }
|
||||||
|
@ -36,7 +38,9 @@ namespace NzbDrone.Api.Config
|
||||||
DailyEpisodeFormat = model.DailyEpisodeFormat,
|
DailyEpisodeFormat = model.DailyEpisodeFormat,
|
||||||
AnimeEpisodeFormat = model.AnimeEpisodeFormat,
|
AnimeEpisodeFormat = model.AnimeEpisodeFormat,
|
||||||
SeriesFolderFormat = model.SeriesFolderFormat,
|
SeriesFolderFormat = model.SeriesFolderFormat,
|
||||||
SeasonFolderFormat = model.SeasonFolderFormat
|
SeasonFolderFormat = model.SeasonFolderFormat,
|
||||||
|
StandardMovieFormat = model.StandardMovieFormat,
|
||||||
|
MovieFolderFormat = model.MovieFolderFormat
|
||||||
//IncludeSeriesTitle
|
//IncludeSeriesTitle
|
||||||
//IncludeEpisodeTitle
|
//IncludeEpisodeTitle
|
||||||
//IncludeQuality
|
//IncludeQuality
|
||||||
|
@ -64,12 +68,14 @@ namespace NzbDrone.Api.Config
|
||||||
|
|
||||||
RenameEpisodes = resource.RenameEpisodes,
|
RenameEpisodes = resource.RenameEpisodes,
|
||||||
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
||||||
MultiEpisodeStyle = resource.MultiEpisodeStyle,
|
//MultiEpisodeStyle = resource.MultiEpisodeStyle,
|
||||||
StandardEpisodeFormat = resource.StandardEpisodeFormat,
|
//StandardEpisodeFormat = resource.StandardEpisodeFormat,
|
||||||
DailyEpisodeFormat = resource.DailyEpisodeFormat,
|
//DailyEpisodeFormat = resource.DailyEpisodeFormat,
|
||||||
AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
|
//AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
|
||||||
SeriesFolderFormat = resource.SeriesFolderFormat,
|
//SeriesFolderFormat = resource.SeriesFolderFormat,
|
||||||
SeasonFolderFormat = resource.SeasonFolderFormat
|
//SeasonFolderFormat = resource.SeasonFolderFormat,
|
||||||
|
StandardMovieFormat = resource.StandardMovieFormat,
|
||||||
|
MovieFolderFormat = resource.MovieFolderFormat
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,5 +9,8 @@
|
||||||
public string AnimeMultiEpisodeExample { get; set; }
|
public string AnimeMultiEpisodeExample { get; set; }
|
||||||
public string SeriesFolderExample { get; set; }
|
public string SeriesFolderExample { get; set; }
|
||||||
public string SeasonFolderExample { get; set; }
|
public string SeasonFolderExample { get; set; }
|
||||||
|
|
||||||
|
public string MovieExample { get; set; }
|
||||||
|
public string MovieFolderExample { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@ using Nancy;
|
||||||
using NzbDrone.Api.Episodes;
|
using NzbDrone.Api.Episodes;
|
||||||
using NzbDrone.Api.Extensions;
|
using NzbDrone.Api.Extensions;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
|
using NzbDrone.Api.Movie;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
@ -34,12 +35,18 @@ namespace NzbDrone.Api.History
|
||||||
|
|
||||||
resource.Series = model.Series.ToResource();
|
resource.Series = model.Series.ToResource();
|
||||||
resource.Episode = model.Episode.ToResource();
|
resource.Episode = model.Episode.ToResource();
|
||||||
|
resource.Movie = model.Movie.ToResource();
|
||||||
|
|
||||||
if (model.Series != null)
|
if (model.Series != null)
|
||||||
{
|
{
|
||||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Series.Profile.Value, model.Quality);
|
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Series.Profile.Value, model.Quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model.Movie != null)
|
||||||
|
{
|
||||||
|
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Movie.Profile.Value, model.Quality);
|
||||||
|
}
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +54,8 @@ namespace NzbDrone.Api.History
|
||||||
{
|
{
|
||||||
var episodeId = Request.Query.EpisodeId;
|
var episodeId = Request.Query.EpisodeId;
|
||||||
|
|
||||||
|
var movieId = Request.Query.MovieId;
|
||||||
|
|
||||||
var pagingSpec = pagingResource.MapToPagingSpec<HistoryResource, Core.History.History>("date", SortDirection.Descending);
|
var pagingSpec = pagingResource.MapToPagingSpec<HistoryResource, Core.History.History>("date", SortDirection.Descending);
|
||||||
|
|
||||||
if (pagingResource.FilterKey == "eventType")
|
if (pagingResource.FilterKey == "eventType")
|
||||||
|
@ -61,6 +70,12 @@ namespace NzbDrone.Api.History
|
||||||
pagingSpec.FilterExpression = h => h.EpisodeId == i;
|
pagingSpec.FilterExpression = h => h.EpisodeId == i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (movieId.HasValue)
|
||||||
|
{
|
||||||
|
int i = (int)movieId;
|
||||||
|
pagingSpec.FilterExpression = h => h.MovieId == i;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyToPage(_historyService.Paged, pagingSpec, MapToResource);
|
return ApplyToPage(_historyService.Paged, pagingSpec, MapToResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using NzbDrone.Api.Episodes;
|
using NzbDrone.Api.Episodes;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
|
using NzbDrone.Api.Movie;
|
||||||
using NzbDrone.Core.History;
|
using NzbDrone.Core.History;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ namespace NzbDrone.Api.History
|
||||||
public class HistoryResource : RestResource
|
public class HistoryResource : RestResource
|
||||||
{
|
{
|
||||||
public int EpisodeId { get; set; }
|
public int EpisodeId { get; set; }
|
||||||
|
public int MovieId { get; set; }
|
||||||
public int SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
public string SourceTitle { get; set; }
|
public string SourceTitle { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
|
@ -22,7 +24,7 @@ namespace NzbDrone.Api.History
|
||||||
public HistoryEventType EventType { get; set; }
|
public HistoryEventType EventType { get; set; }
|
||||||
|
|
||||||
public Dictionary<string, string> Data { get; set; }
|
public Dictionary<string, string> Data { get; set; }
|
||||||
|
public MovieResource Movie { get; set; }
|
||||||
public EpisodeResource Episode { get; set; }
|
public EpisodeResource Episode { get; set; }
|
||||||
public SeriesResource Series { get; set; }
|
public SeriesResource Series { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -39,6 +41,7 @@ namespace NzbDrone.Api.History
|
||||||
|
|
||||||
EpisodeId = model.EpisodeId,
|
EpisodeId = model.EpisodeId,
|
||||||
SeriesId = model.SeriesId,
|
SeriesId = model.SeriesId,
|
||||||
|
MovieId = model.MovieId,
|
||||||
SourceTitle = model.SourceTitle,
|
SourceTitle = model.SourceTitle,
|
||||||
Quality = model.Quality,
|
Quality = model.Quality,
|
||||||
//QualityCutoffNotMet
|
//QualityCutoffNotMet
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
private readonly ICached<RemoteEpisode> _remoteEpisodeCache;
|
private readonly ICached<RemoteEpisode> _remoteEpisodeCache;
|
||||||
|
private readonly ICached<RemoteMovie> _remoteMovieCache;
|
||||||
|
|
||||||
public ReleaseModule(IFetchAndParseRss rssFetcherAndParser,
|
public ReleaseModule(IFetchAndParseRss rssFetcherAndParser,
|
||||||
ISearchForNzb nzbSearchService,
|
ISearchForNzb nzbSearchService,
|
||||||
|
@ -49,6 +50,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
PostValidator.RuleFor(s => s.Guid).NotEmpty();
|
PostValidator.RuleFor(s => s.Guid).NotEmpty();
|
||||||
|
|
||||||
_remoteEpisodeCache = cacheManager.GetCache<RemoteEpisode>(GetType(), "remoteEpisodes");
|
_remoteEpisodeCache = cacheManager.GetCache<RemoteEpisode>(GetType(), "remoteEpisodes");
|
||||||
|
_remoteMovieCache = cacheManager.GetCache<RemoteMovie>(GetType(), "remoteMovies");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response DownloadRelease(ReleaseResource release)
|
private Response DownloadRelease(ReleaseResource release)
|
||||||
|
@ -59,7 +61,26 @@ namespace NzbDrone.Api.Indexers
|
||||||
{
|
{
|
||||||
_logger.Debug("Couldn't find requested release in cache, cache timeout probably expired.");
|
_logger.Debug("Couldn't find requested release in cache, cache timeout probably expired.");
|
||||||
|
|
||||||
return new NotFoundResponse();
|
var remoteMovie = _remoteMovieCache.Find(release.Guid);
|
||||||
|
|
||||||
|
if (remoteMovie == null)
|
||||||
|
{
|
||||||
|
return new NotFoundResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_downloadService.DownloadReport(remoteMovie);
|
||||||
|
}
|
||||||
|
catch (ReleaseDownloadException ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, ex.Message);
|
||||||
|
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return release.AsResponse();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -82,6 +103,11 @@ namespace NzbDrone.Api.Indexers
|
||||||
return GetEpisodeReleases(Request.Query.episodeId);
|
return GetEpisodeReleases(Request.Query.episodeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Request.Query.movieId != null)
|
||||||
|
{
|
||||||
|
return GetMovieReleases(Request.Query.movieId);
|
||||||
|
}
|
||||||
|
|
||||||
return GetRss();
|
return GetRss();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +128,27 @@ namespace NzbDrone.Api.Indexers
|
||||||
return new List<ReleaseResource>();
|
return new List<ReleaseResource>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ReleaseResource> GetMovieReleases(int movieId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var decisions = _nzbSearchService.MovieSearch(movieId, true);
|
||||||
|
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisionsForMovies(decisions);
|
||||||
|
|
||||||
|
return MapDecisions(prioritizedDecisions);
|
||||||
|
}
|
||||||
|
catch (NotImplementedException ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, "One or more indexer you selected does not support movie search yet: " + ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, "Movie search failed: " + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<ReleaseResource>();
|
||||||
|
}
|
||||||
|
|
||||||
private List<ReleaseResource> GetRss()
|
private List<ReleaseResource> GetRss()
|
||||||
{
|
{
|
||||||
var reports = _rssFetcherAndParser.Fetch();
|
var reports = _rssFetcherAndParser.Fetch();
|
||||||
|
@ -113,7 +160,15 @@ namespace NzbDrone.Api.Indexers
|
||||||
|
|
||||||
protected override ReleaseResource MapDecision(DownloadDecision decision, int initialWeight)
|
protected override ReleaseResource MapDecision(DownloadDecision decision, int initialWeight)
|
||||||
{
|
{
|
||||||
_remoteEpisodeCache.Set(decision.RemoteEpisode.Release.Guid, decision.RemoteEpisode, TimeSpan.FromMinutes(30));
|
if (decision.IsForMovie)
|
||||||
|
{
|
||||||
|
_remoteMovieCache.Set(decision.RemoteMovie.Release.Guid, decision.RemoteMovie, TimeSpan.FromMinutes(30));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_remoteEpisodeCache.Set(decision.RemoteEpisode.Release.Guid, decision.RemoteEpisode, TimeSpan.FromMinutes(30));
|
||||||
|
}
|
||||||
|
|
||||||
return base.MapDecision(decision, initialWeight);
|
return base.MapDecision(decision, initialWeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
public string Indexer { get; set; }
|
public string Indexer { get; set; }
|
||||||
public string ReleaseGroup { get; set; }
|
public string ReleaseGroup { get; set; }
|
||||||
public string ReleaseHash { get; set; }
|
public string ReleaseHash { get; set; }
|
||||||
|
public string Edition { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public bool FullSeason { get; set; }
|
public bool FullSeason { get; set; }
|
||||||
public int SeasonNumber { get; set; }
|
public int SeasonNumber { get; set; }
|
||||||
|
@ -86,6 +87,60 @@ namespace NzbDrone.Api.Indexers
|
||||||
var parsedEpisodeInfo = model.RemoteEpisode.ParsedEpisodeInfo;
|
var parsedEpisodeInfo = model.RemoteEpisode.ParsedEpisodeInfo;
|
||||||
var remoteEpisode = model.RemoteEpisode;
|
var remoteEpisode = model.RemoteEpisode;
|
||||||
var torrentInfo = (model.RemoteEpisode.Release as TorrentInfo) ?? new TorrentInfo();
|
var torrentInfo = (model.RemoteEpisode.Release as TorrentInfo) ?? new TorrentInfo();
|
||||||
|
var downloadAllowed = model.RemoteEpisode.DownloadAllowed;
|
||||||
|
if (model.IsForMovie)
|
||||||
|
{
|
||||||
|
downloadAllowed = model.RemoteMovie.DownloadAllowed;
|
||||||
|
var parsedMovieInfo = model.RemoteMovie.ParsedMovieInfo;
|
||||||
|
|
||||||
|
return new ReleaseResource
|
||||||
|
{
|
||||||
|
Guid = releaseInfo.Guid,
|
||||||
|
Quality = parsedMovieInfo.Quality,
|
||||||
|
//QualityWeight
|
||||||
|
Age = releaseInfo.Age,
|
||||||
|
AgeHours = releaseInfo.AgeHours,
|
||||||
|
AgeMinutes = releaseInfo.AgeMinutes,
|
||||||
|
Size = releaseInfo.Size,
|
||||||
|
IndexerId = releaseInfo.IndexerId,
|
||||||
|
Indexer = releaseInfo.Indexer,
|
||||||
|
ReleaseGroup = parsedMovieInfo.ReleaseGroup,
|
||||||
|
ReleaseHash = parsedMovieInfo.ReleaseHash,
|
||||||
|
Title = releaseInfo.Title,
|
||||||
|
//FullSeason = parsedMovieInfo.FullSeason,
|
||||||
|
//SeasonNumber = parsedMovieInfo.SeasonNumber,
|
||||||
|
Language = parsedMovieInfo.Language,
|
||||||
|
AirDate = "",
|
||||||
|
SeriesTitle = parsedMovieInfo.MovieTitle,
|
||||||
|
EpisodeNumbers = new int[0],
|
||||||
|
AbsoluteEpisodeNumbers = new int[0],
|
||||||
|
Approved = model.Approved,
|
||||||
|
TemporarilyRejected = model.TemporarilyRejected,
|
||||||
|
Rejected = model.Rejected,
|
||||||
|
TvdbId = releaseInfo.TvdbId,
|
||||||
|
TvRageId = releaseInfo.TvRageId,
|
||||||
|
Rejections = model.Rejections.Select(r => r.Reason).ToList(),
|
||||||
|
PublishDate = releaseInfo.PublishDate,
|
||||||
|
CommentUrl = releaseInfo.CommentUrl,
|
||||||
|
DownloadUrl = releaseInfo.DownloadUrl,
|
||||||
|
InfoUrl = releaseInfo.InfoUrl,
|
||||||
|
DownloadAllowed = downloadAllowed,
|
||||||
|
//ReleaseWeight
|
||||||
|
|
||||||
|
MagnetUrl = torrentInfo.MagnetUrl,
|
||||||
|
InfoHash = torrentInfo.InfoHash,
|
||||||
|
Seeders = torrentInfo.Seeders,
|
||||||
|
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
|
||||||
|
Protocol = releaseInfo.DownloadProtocol,
|
||||||
|
|
||||||
|
Edition = parsedMovieInfo.Edition,
|
||||||
|
|
||||||
|
IsDaily = false,
|
||||||
|
IsAbsoluteNumbering = false,
|
||||||
|
IsPossibleSpecialEpisode = false,
|
||||||
|
//Special = parsedMovieInfo.Special,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
|
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
|
||||||
return new ReleaseResource
|
return new ReleaseResource
|
||||||
|
@ -119,7 +174,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
CommentUrl = releaseInfo.CommentUrl,
|
CommentUrl = releaseInfo.CommentUrl,
|
||||||
DownloadUrl = releaseInfo.DownloadUrl,
|
DownloadUrl = releaseInfo.DownloadUrl,
|
||||||
InfoUrl = releaseInfo.InfoUrl,
|
InfoUrl = releaseInfo.InfoUrl,
|
||||||
DownloadAllowed = remoteEpisode.DownloadAllowed,
|
DownloadAllowed = downloadAllowed,
|
||||||
//ReleaseWeight
|
//ReleaseWeight
|
||||||
|
|
||||||
MagnetUrl = torrentInfo.MagnetUrl,
|
MagnetUrl = torrentInfo.MagnetUrl,
|
||||||
|
|
11
src/NzbDrone.Api/Movies/MovieModule.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movies
|
||||||
|
{
|
||||||
|
class MovieModule
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
35
src/NzbDrone.Api/Movies/RenameMovieModule.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movies
|
||||||
|
{
|
||||||
|
public class RenameMovieModule : NzbDroneRestModule<RenameMovieResource>
|
||||||
|
{
|
||||||
|
private readonly IRenameMovieFileService _renameMovieFileService;
|
||||||
|
|
||||||
|
public RenameMovieModule(IRenameMovieFileService renameMovieFileService)
|
||||||
|
: base("rename")
|
||||||
|
{
|
||||||
|
_renameMovieFileService = renameMovieFileService;
|
||||||
|
|
||||||
|
GetResourceAll = GetMovies; //TODO: GetResourceSingle?
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RenameMovieResource> GetMovies()
|
||||||
|
{
|
||||||
|
if(!Request.Query.MovieId.HasValue)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("movieId is missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
var movieId = (int)Request.Query.MovieId;
|
||||||
|
|
||||||
|
return _renameMovieFileService.GetRenamePreviews(movieId).ToResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
35
src/NzbDrone.Api/Movies/RenameMovieResource.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movies
|
||||||
|
{
|
||||||
|
public class RenameMovieResource : RestResource
|
||||||
|
{
|
||||||
|
public int MovieId { get; set; }
|
||||||
|
public int MovieFileId { get; set; }
|
||||||
|
public string ExistingPath { get; set; }
|
||||||
|
public string NewPath { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RenameMovieResourceMapper
|
||||||
|
{
|
||||||
|
public static RenameMovieResource ToResource(this Core.MediaFiles.RenameMovieFilePreview model)
|
||||||
|
{
|
||||||
|
if (model == null) return null;
|
||||||
|
|
||||||
|
return new RenameMovieResource
|
||||||
|
{
|
||||||
|
MovieId = model.MovieId,
|
||||||
|
MovieFileId = model.MovieFileId,
|
||||||
|
ExistingPath = model.ExistingPath,
|
||||||
|
NewPath = model.NewPath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<RenameMovieResource> ToResource(this IEnumerable<Core.MediaFiles.RenameMovieFilePreview> models)
|
||||||
|
{
|
||||||
|
return models.Select(ToResource).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,6 +116,9 @@
|
||||||
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
|
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
|
||||||
<Compile Include="Indexers\ReleaseModuleBase.cs" />
|
<Compile Include="Indexers\ReleaseModuleBase.cs" />
|
||||||
<Compile Include="Indexers\ReleasePushModule.cs" />
|
<Compile Include="Indexers\ReleasePushModule.cs" />
|
||||||
|
<Compile Include="Movies\MovieModule.cs" />
|
||||||
|
<Compile Include="Movies\RenameMovieModule.cs" />
|
||||||
|
<Compile Include="Movies\RenameMovieResource.cs" />
|
||||||
<Compile Include="Parse\ParseModule.cs" />
|
<Compile Include="Parse\ParseModule.cs" />
|
||||||
<Compile Include="Parse\ParseResource.cs" />
|
<Compile Include="Parse\ParseResource.cs" />
|
||||||
<Compile Include="ManualImport\ManualImportModule.cs" />
|
<Compile Include="ManualImport\ManualImportModule.cs" />
|
||||||
|
@ -231,8 +234,11 @@
|
||||||
<Compile Include="Series\SeasonResource.cs" />
|
<Compile Include="Series\SeasonResource.cs" />
|
||||||
<Compile Include="SeasonPass\SeasonPassModule.cs" />
|
<Compile Include="SeasonPass\SeasonPassModule.cs" />
|
||||||
<Compile Include="Series\SeriesEditorModule.cs" />
|
<Compile Include="Series\SeriesEditorModule.cs" />
|
||||||
|
<Compile Include="Series\MovieLookupModule.cs" />
|
||||||
<Compile Include="Series\SeriesLookupModule.cs" />
|
<Compile Include="Series\SeriesLookupModule.cs" />
|
||||||
|
<Compile Include="Series\MovieModule.cs" />
|
||||||
<Compile Include="Series\SeriesModule.cs" />
|
<Compile Include="Series\SeriesModule.cs" />
|
||||||
|
<Compile Include="Series\MovieResource.cs" />
|
||||||
<Compile Include="Series\SeriesResource.cs" />
|
<Compile Include="Series\SeriesResource.cs" />
|
||||||
<Compile Include="Series\SeasonStatisticsResource.cs" />
|
<Compile Include="Series\SeasonStatisticsResource.cs" />
|
||||||
<Compile Include="System\Backup\BackupModule.cs" />
|
<Compile Include="System\Backup\BackupModule.cs" />
|
||||||
|
|
|
@ -6,6 +6,5 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
[assembly: Guid("4c0922d7-979e-4ff7-b44b-b8ac2100eeb5")]
|
[assembly: Guid("4c0922d7-979e-4ff7-b44b-b8ac2100eeb5")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.0.0.*")]
|
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("NzbDrone.Core")]
|
[assembly: InternalsVisibleTo("NzbDrone.Core")]
|
||||||
|
|
|
@ -4,6 +4,7 @@ using NzbDrone.Api.REST;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
using NzbDrone.Api.Episodes;
|
using NzbDrone.Api.Episodes;
|
||||||
|
using NzbDrone.Api.Movie;
|
||||||
using NzbDrone.Core.Download.TrackedDownloads;
|
using NzbDrone.Core.Download.TrackedDownloads;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -14,6 +15,7 @@ namespace NzbDrone.Api.Queue
|
||||||
{
|
{
|
||||||
public SeriesResource Series { get; set; }
|
public SeriesResource Series { get; set; }
|
||||||
public EpisodeResource Episode { get; set; }
|
public EpisodeResource Episode { get; set; }
|
||||||
|
public MovieResource Movie { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public decimal Size { get; set; }
|
public decimal Size { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
@ -49,7 +51,8 @@ namespace NzbDrone.Api.Queue
|
||||||
TrackedDownloadStatus = model.TrackedDownloadStatus,
|
TrackedDownloadStatus = model.TrackedDownloadStatus,
|
||||||
StatusMessages = model.StatusMessages,
|
StatusMessages = model.StatusMessages,
|
||||||
DownloadId = model.DownloadId,
|
DownloadId = model.DownloadId,
|
||||||
Protocol = model.Protocol
|
Protocol = model.Protocol,
|
||||||
|
Movie = model.Movie.ToResource()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
src/NzbDrone.Api/Series/MovieLookupModule.cs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Nancy;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Core.MediaCover;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
public class MovieLookupModule : NzbDroneRestModule<MovieResource>
|
||||||
|
{
|
||||||
|
private readonly ISearchForNewMovie _searchProxy;
|
||||||
|
|
||||||
|
public MovieLookupModule(ISearchForNewMovie searchProxy)
|
||||||
|
: base("/movies/lookup")
|
||||||
|
{
|
||||||
|
_searchProxy = searchProxy;
|
||||||
|
Get["/"] = x => Search();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Response Search()
|
||||||
|
{
|
||||||
|
var imdbResults = _searchProxy.SearchForNewMovie((string)Request.Query.term);
|
||||||
|
return MapToResource(imdbResults).AsResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
||||||
|
{
|
||||||
|
foreach (var currentSeries in movies)
|
||||||
|
{
|
||||||
|
var resource = currentSeries.ToResource();
|
||||||
|
var poster = currentSeries.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||||
|
if (poster != null)
|
||||||
|
{
|
||||||
|
resource.RemotePoster = poster.Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
225
src/NzbDrone.Api/Series/MovieModule.cs
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using FluentValidation;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Datastore.Events;
|
||||||
|
using NzbDrone.Core.MediaCover;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.MovieStats;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Tv.Events;
|
||||||
|
using NzbDrone.Core.Validation.Paths;
|
||||||
|
using NzbDrone.Core.DataAugmentation.Scene;
|
||||||
|
using NzbDrone.Core.Validation;
|
||||||
|
using NzbDrone.SignalR;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
public class MovieModule : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>,
|
||||||
|
IHandle<EpisodeImportedEvent>,
|
||||||
|
IHandle<EpisodeFileDeletedEvent>,
|
||||||
|
IHandle<MovieUpdatedEvent>,
|
||||||
|
IHandle<MovieEditedEvent>,
|
||||||
|
IHandle<MovieDeletedEvent>,
|
||||||
|
IHandle<MovieRenamedEvent>,
|
||||||
|
IHandle<MediaCoversUpdatedEvent>
|
||||||
|
|
||||||
|
{
|
||||||
|
private readonly IMovieService _moviesService;
|
||||||
|
private readonly IMovieStatisticsService _moviesStatisticsService;
|
||||||
|
private readonly IMapCoversToLocal _coverMapper;
|
||||||
|
|
||||||
|
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
|
IMovieService moviesService,
|
||||||
|
IMovieStatisticsService moviesStatisticsService,
|
||||||
|
ISceneMappingService sceneMappingService,
|
||||||
|
IMapCoversToLocal coverMapper,
|
||||||
|
RootFolderValidator rootFolderValidator,
|
||||||
|
MoviePathValidator moviesPathValidator,
|
||||||
|
MovieExistsValidator moviesExistsValidator,
|
||||||
|
DroneFactoryValidator droneFactoryValidator,
|
||||||
|
MovieAncestorValidator moviesAncestorValidator,
|
||||||
|
ProfileExistsValidator profileExistsValidator
|
||||||
|
)
|
||||||
|
: base(signalRBroadcaster)
|
||||||
|
{
|
||||||
|
_moviesService = moviesService;
|
||||||
|
_moviesStatisticsService = moviesStatisticsService;
|
||||||
|
|
||||||
|
_coverMapper = coverMapper;
|
||||||
|
|
||||||
|
GetResourceAll = AllMovie;
|
||||||
|
GetResourceById = GetMovie;
|
||||||
|
CreateResource = AddMovie;
|
||||||
|
UpdateResource = UpdateMovie;
|
||||||
|
DeleteResource = DeleteMovie;
|
||||||
|
|
||||||
|
Validation.RuleBuilderExtensions.ValidId(SharedValidator.RuleFor(s => s.ProfileId));
|
||||||
|
|
||||||
|
SharedValidator.RuleFor(s => s.Path)
|
||||||
|
.Cascade(CascadeMode.StopOnFirstFailure)
|
||||||
|
.IsValidPath()
|
||||||
|
.SetValidator(rootFolderValidator)
|
||||||
|
.SetValidator(moviesPathValidator)
|
||||||
|
.SetValidator(droneFactoryValidator)
|
||||||
|
.SetValidator(moviesAncestorValidator)
|
||||||
|
.When(s => !s.Path.IsNullOrWhiteSpace());
|
||||||
|
|
||||||
|
SharedValidator.RuleFor(s => s.ProfileId).SetValidator(profileExistsValidator);
|
||||||
|
|
||||||
|
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
|
||||||
|
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
|
||||||
|
PostValidator.RuleFor(s => s.Title).NotEmpty();
|
||||||
|
PostValidator.RuleFor(s => s.TmdbId).NotNull().NotEmpty().SetValidator(moviesExistsValidator);
|
||||||
|
|
||||||
|
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MovieResource GetMovie(int id)
|
||||||
|
{
|
||||||
|
var movies = _moviesService.GetMovie(id);
|
||||||
|
return MapToResource(movies);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MovieResource MapToResource(Core.Tv.Movie movies)
|
||||||
|
{
|
||||||
|
if (movies == null) return null;
|
||||||
|
|
||||||
|
var resource = movies.ToResource();
|
||||||
|
MapCoversToLocal(resource);
|
||||||
|
FetchAndLinkMovieStatistics(resource);
|
||||||
|
PopulateAlternateTitles(resource);
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MovieResource> AllMovie()
|
||||||
|
{
|
||||||
|
var moviesStats = _moviesStatisticsService.MovieStatistics();
|
||||||
|
var moviesResources = _moviesService.GetAllMovies().ToResource();
|
||||||
|
|
||||||
|
MapCoversToLocal(moviesResources.ToArray());
|
||||||
|
LinkMovieStatistics(moviesResources, moviesStats);
|
||||||
|
PopulateAlternateTitles(moviesResources);
|
||||||
|
|
||||||
|
return moviesResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int AddMovie(MovieResource moviesResource)
|
||||||
|
{
|
||||||
|
var model = moviesResource.ToModel();
|
||||||
|
|
||||||
|
return _moviesService.AddMovie(model).Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateMovie(MovieResource moviesResource)
|
||||||
|
{
|
||||||
|
var model = moviesResource.ToModel(_moviesService.GetMovie(moviesResource.Id));
|
||||||
|
|
||||||
|
_moviesService.UpdateMovie(model);
|
||||||
|
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, moviesResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeleteMovie(int id)
|
||||||
|
{
|
||||||
|
var deleteFiles = false;
|
||||||
|
var deleteFilesQuery = Request.Query.deleteFiles;
|
||||||
|
|
||||||
|
if (deleteFilesQuery.HasValue)
|
||||||
|
{
|
||||||
|
deleteFiles = Convert.ToBoolean(deleteFilesQuery.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
_moviesService.DeleteMovie(id, deleteFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MapCoversToLocal(params MovieResource[] movies)
|
||||||
|
{
|
||||||
|
foreach (var moviesResource in movies)
|
||||||
|
{
|
||||||
|
_coverMapper.ConvertToLocalUrls(moviesResource.Id, moviesResource.Images);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FetchAndLinkMovieStatistics(MovieResource resource)
|
||||||
|
{
|
||||||
|
LinkMovieStatistics(resource, _moviesStatisticsService.MovieStatistics(resource.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LinkMovieStatistics(List<MovieResource> resources, List<MovieStatistics> moviesStatistics)
|
||||||
|
{
|
||||||
|
var dictMovieStats = moviesStatistics.ToDictionary(v => v.MovieId);
|
||||||
|
|
||||||
|
foreach (var movies in resources)
|
||||||
|
{
|
||||||
|
var stats = dictMovieStats.GetValueOrDefault(movies.Id);
|
||||||
|
if (stats == null) continue;
|
||||||
|
|
||||||
|
LinkMovieStatistics(movies, stats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics)
|
||||||
|
{
|
||||||
|
resource.SizeOnDisk = moviesStatistics.SizeOnDisk;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateAlternateTitles(List<MovieResource> resources)
|
||||||
|
{
|
||||||
|
foreach (var resource in resources)
|
||||||
|
{
|
||||||
|
PopulateAlternateTitles(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateAlternateTitles(MovieResource resource)
|
||||||
|
{
|
||||||
|
//var mappings = null;//_sceneMappingService.FindByTvdbId(resource.TvdbId);
|
||||||
|
|
||||||
|
//if (mappings == null) return;
|
||||||
|
|
||||||
|
//resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(EpisodeImportedEvent message)
|
||||||
|
{
|
||||||
|
//BroadcastResourceChange(ModelAction.Updated, message.ImportedEpisode.MovieId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(EpisodeFileDeletedEvent message)
|
||||||
|
{
|
||||||
|
if (message.Reason == DeleteMediaFileReason.Upgrade) return;
|
||||||
|
|
||||||
|
//BroadcastResourceChange(ModelAction.Updated, message.EpisodeFile.MovieId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MovieUpdatedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MovieEditedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MovieDeletedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastResourceChange(ModelAction.Deleted, message.Movie.ToResource());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MovieRenamedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MediaCoversUpdatedEvent message)
|
||||||
|
{
|
||||||
|
//BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
216
src/NzbDrone.Api/Series/MovieResource.cs
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.MediaCover;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Api.Series;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
public class MovieResource : RestResource
|
||||||
|
{
|
||||||
|
public MovieResource()
|
||||||
|
{
|
||||||
|
Monitored = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Todo: Sorters should be done completely on the client
|
||||||
|
//Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing?
|
||||||
|
//Todo: We should get the entire Profile instead of ID and Name separately
|
||||||
|
|
||||||
|
//View Only
|
||||||
|
public string Title { get; set; }
|
||||||
|
public List<AlternateTitleResource> AlternateTitles { get; set; }
|
||||||
|
public string SortTitle { get; set; }
|
||||||
|
public long? SizeOnDisk { get; set; }
|
||||||
|
public MovieStatusType Status { get; set; }
|
||||||
|
public string Overview { get; set; }
|
||||||
|
public DateTime? InCinemas { get; set; }
|
||||||
|
public DateTime? PhysicalRelease { get; set; }
|
||||||
|
public List<MediaCover> Images { get; set; }
|
||||||
|
public string Website { get; set; }
|
||||||
|
public bool Downloaded { get; set; }
|
||||||
|
public string RemotePoster { get; set; }
|
||||||
|
public int Year { get; set; }
|
||||||
|
public bool HasFile { get; set; }
|
||||||
|
|
||||||
|
//View & Edit
|
||||||
|
public string Path { get; set; }
|
||||||
|
public int ProfileId { get; set; }
|
||||||
|
|
||||||
|
//Editing Only
|
||||||
|
public bool Monitored { get; set; }
|
||||||
|
public int Runtime { get; set; }
|
||||||
|
public DateTime? LastInfoSync { get; set; }
|
||||||
|
public string CleanTitle { get; set; }
|
||||||
|
public string ImdbId { get; set; }
|
||||||
|
public int TmdbId { get; set; }
|
||||||
|
public string TitleSlug { get; set; }
|
||||||
|
public string RootFolderPath { get; set; }
|
||||||
|
public string Certification { get; set; }
|
||||||
|
public List<string> Genres { get; set; }
|
||||||
|
public HashSet<int> Tags { get; set; }
|
||||||
|
public DateTime Added { get; set; }
|
||||||
|
public AddMovieOptions AddOptions { get; set; }
|
||||||
|
public Ratings Ratings { get; set; }
|
||||||
|
public List<string> AlternativeTitles { get; set; }
|
||||||
|
|
||||||
|
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
||||||
|
|
||||||
|
//Used to support legacy consumers
|
||||||
|
public int QualityProfileId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ProfileId;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value > 0 && ProfileId == 0)
|
||||||
|
{
|
||||||
|
ProfileId = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MovieResourceMapper
|
||||||
|
{
|
||||||
|
public static MovieResource ToResource(this Core.Tv.Movie model)
|
||||||
|
{
|
||||||
|
if (model == null) return null;
|
||||||
|
|
||||||
|
|
||||||
|
long size = 0;
|
||||||
|
bool downloaded = false;
|
||||||
|
|
||||||
|
|
||||||
|
if(model.MovieFile != null)
|
||||||
|
{
|
||||||
|
model.MovieFile.LazyLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.MovieFile != null && model.MovieFile.IsLoaded && model.MovieFile.Value != null)
|
||||||
|
{
|
||||||
|
size = model.MovieFile.Value.Size;
|
||||||
|
downloaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MovieResource
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
TmdbId = model.TmdbId,
|
||||||
|
Title = model.Title,
|
||||||
|
//AlternateTitles
|
||||||
|
SortTitle = model.SortTitle,
|
||||||
|
InCinemas = model.InCinemas,
|
||||||
|
PhysicalRelease = model.PhysicalRelease,
|
||||||
|
HasFile = model.HasFile,
|
||||||
|
Downloaded = downloaded,
|
||||||
|
//TotalEpisodeCount
|
||||||
|
//EpisodeCount
|
||||||
|
//EpisodeFileCount
|
||||||
|
//SizeOnDisk
|
||||||
|
Status = model.Status,
|
||||||
|
Overview = model.Overview,
|
||||||
|
//NextAiring
|
||||||
|
//PreviousAiring
|
||||||
|
Images = model.Images,
|
||||||
|
|
||||||
|
Year = model.Year,
|
||||||
|
|
||||||
|
Path = model.Path,
|
||||||
|
ProfileId = model.ProfileId,
|
||||||
|
|
||||||
|
Monitored = model.Monitored,
|
||||||
|
|
||||||
|
SizeOnDisk = size,
|
||||||
|
|
||||||
|
Runtime = model.Runtime,
|
||||||
|
LastInfoSync = model.LastInfoSync,
|
||||||
|
CleanTitle = model.CleanTitle,
|
||||||
|
ImdbId = model.ImdbId,
|
||||||
|
TitleSlug = model.TitleSlug,
|
||||||
|
RootFolderPath = model.RootFolderPath,
|
||||||
|
Certification = model.Certification,
|
||||||
|
Website = model.Website,
|
||||||
|
Genres = model.Genres,
|
||||||
|
Tags = model.Tags,
|
||||||
|
Added = model.Added,
|
||||||
|
AddOptions = model.AddOptions,
|
||||||
|
AlternativeTitles = model.AlternativeTitles,
|
||||||
|
Ratings = model.Ratings
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Core.Tv.Movie ToModel(this MovieResource resource)
|
||||||
|
{
|
||||||
|
if (resource == null) return null;
|
||||||
|
|
||||||
|
return new Core.Tv.Movie
|
||||||
|
{
|
||||||
|
Id = resource.Id,
|
||||||
|
TmdbId = resource.TmdbId,
|
||||||
|
|
||||||
|
Title = resource.Title,
|
||||||
|
//AlternateTitles
|
||||||
|
SortTitle = resource.SortTitle,
|
||||||
|
InCinemas = resource.InCinemas,
|
||||||
|
PhysicalRelease = resource.PhysicalRelease,
|
||||||
|
//TotalEpisodeCount
|
||||||
|
//EpisodeCount
|
||||||
|
//EpisodeFileCount
|
||||||
|
//SizeOnDisk
|
||||||
|
Overview = resource.Overview,
|
||||||
|
//NextAiring
|
||||||
|
//PreviousAiring
|
||||||
|
Images = resource.Images,
|
||||||
|
|
||||||
|
Year = resource.Year,
|
||||||
|
|
||||||
|
Path = resource.Path,
|
||||||
|
ProfileId = resource.ProfileId,
|
||||||
|
|
||||||
|
Monitored = resource.Monitored,
|
||||||
|
|
||||||
|
Runtime = resource.Runtime,
|
||||||
|
LastInfoSync = resource.LastInfoSync,
|
||||||
|
CleanTitle = resource.CleanTitle,
|
||||||
|
ImdbId = resource.ImdbId,
|
||||||
|
TitleSlug = resource.TitleSlug,
|
||||||
|
RootFolderPath = resource.RootFolderPath,
|
||||||
|
Certification = resource.Certification,
|
||||||
|
Website = resource.Website,
|
||||||
|
Genres = resource.Genres,
|
||||||
|
Tags = resource.Tags,
|
||||||
|
Added = resource.Added,
|
||||||
|
AddOptions = resource.AddOptions,
|
||||||
|
AlternativeTitles = resource.AlternativeTitles,
|
||||||
|
Ratings = resource.Ratings
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Core.Tv.Movie ToModel(this MovieResource resource, Core.Tv.Movie movie)
|
||||||
|
{
|
||||||
|
movie.ImdbId = resource.ImdbId;
|
||||||
|
movie.TmdbId = resource.TmdbId;
|
||||||
|
|
||||||
|
movie.Path = resource.Path;
|
||||||
|
movie.ProfileId = resource.ProfileId;
|
||||||
|
|
||||||
|
movie.Monitored = resource.Monitored;
|
||||||
|
|
||||||
|
movie.RootFolderPath = resource.RootFolderPath;
|
||||||
|
movie.Tags = resource.Tags;
|
||||||
|
movie.AddOptions = resource.AddOptions;
|
||||||
|
|
||||||
|
return movie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MovieResource> ToResource(this IEnumerable<Core.Tv.Movie> movies)
|
||||||
|
{
|
||||||
|
return movies.Select(ToResource).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ namespace NzbDrone.Api.System.Tasks
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string TaskName { get; set; }
|
public string TaskName { get; set; }
|
||||||
public int Interval { get; set; }
|
public double Interval { get; set; }
|
||||||
public DateTime LastExecution { get; set; }
|
public DateTime LastExecution { get; set; }
|
||||||
public DateTime NextExecution { get; set; }
|
public DateTime NextExecution { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ using NzbDrone.Core.Jobs;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Host;
|
using Radarr.Host;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -3,8 +3,9 @@ using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Model;
|
using NzbDrone.Common.Model;
|
||||||
using NzbDrone.Common.Processes;
|
using NzbDrone.Common.Processes;
|
||||||
using NzbDrone.Host;
|
using Radarr.Host;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
using Radarr.Host;
|
||||||
|
|
||||||
namespace NzbDrone.App.Test
|
namespace NzbDrone.App.Test
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,4 +21,3 @@ using System.Runtime.InteropServices;
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("b47d34ef-05e8-4826-8a57-9dd05106c964")]
|
[assembly: Guid("b47d34ef-05e8-4826-8a57-9dd05106c964")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.0.0.*")]
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Host;
|
using Radarr.Host;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
namespace NzbDrone.App.Test
|
namespace NzbDrone.App.Test
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace NzbDrone.Automation.Test
|
||||||
_runner.KillAll();
|
_runner.KillAll();
|
||||||
_runner.Start();
|
_runner.Start();
|
||||||
|
|
||||||
driver.Url = "http://localhost:8989";
|
driver.Url = "http://localhost:7878";
|
||||||
|
|
||||||
var page = new PageBase(driver);
|
var page = new PageBase(driver);
|
||||||
page.WaitForNoSpinner();
|
page.WaitForNoSpinner();
|
||||||
|
|
|
@ -20,5 +20,3 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("6b8945f5-f5b5-4729-865d-f958fbd673d9")]
|
[assembly: Guid("6b8945f5-f5b5-4729-865d-f958fbd673d9")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.0.0.*")]
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace NzbDrone.Common.Test
|
||||||
public void GetValue_Success()
|
public void GetValue_Success()
|
||||||
{
|
{
|
||||||
const string key = "Port";
|
const string key = "Port";
|
||||||
const string value = "8989";
|
const string value = "7878";
|
||||||
|
|
||||||
var result = Subject.GetValue(key, value);
|
var result = Subject.GetValue(key, value);
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ namespace NzbDrone.Common.Test
|
||||||
public void GetInt_Success()
|
public void GetInt_Success()
|
||||||
{
|
{
|
||||||
const string key = "Port";
|
const string key = "Port";
|
||||||
const int value = 8989;
|
const int value = 7878;
|
||||||
|
|
||||||
|
|
||||||
var result = Subject.GetValueInt(key, value);
|
var result = Subject.GetValueInt(key, value);
|
||||||
|
@ -95,7 +95,7 @@ namespace NzbDrone.Common.Test
|
||||||
[Test]
|
[Test]
|
||||||
public void GetPort_Success()
|
public void GetPort_Success()
|
||||||
{
|
{
|
||||||
const int value = 8989;
|
const int value = 7878;
|
||||||
|
|
||||||
|
|
||||||
var result = Subject.Port;
|
var result = Subject.Port;
|
||||||
|
|
|
@ -263,7 +263,7 @@ namespace NzbDrone.Common.Test
|
||||||
[Test]
|
[Test]
|
||||||
public void GetUpdateClientExePath()
|
public void GetUpdateClientExePath()
|
||||||
{
|
{
|
||||||
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\nzbdrone_update\NzbDrone.Update.exe".AsOsAgnostic());
|
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\nzbdrone_update\Radarr.Update.exe".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -5,7 +5,7 @@ using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Host;
|
using Radarr.Host;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Test
|
namespace NzbDrone.Common.Test
|
||||||
|
|
|
@ -6,22 +6,33 @@ namespace NzbDrone.Common.Cloud
|
||||||
{
|
{
|
||||||
IHttpRequestBuilderFactory Services { get; }
|
IHttpRequestBuilderFactory Services { get; }
|
||||||
IHttpRequestBuilderFactory SkyHookTvdb { get; }
|
IHttpRequestBuilderFactory SkyHookTvdb { get; }
|
||||||
|
IHttpRequestBuilderFactory TMDB { get; }
|
||||||
|
IHttpRequestBuilderFactory TMDBSingle { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SonarrCloudRequestBuilder : ISonarrCloudRequestBuilder
|
public class SonarrCloudRequestBuilder : ISonarrCloudRequestBuilder
|
||||||
{
|
{
|
||||||
public SonarrCloudRequestBuilder()
|
public SonarrCloudRequestBuilder()
|
||||||
{
|
{
|
||||||
Services = new HttpRequestBuilder("http://services.sonarr.tv/v1/")
|
Services = new HttpRequestBuilder("http://radarr.aeonlucid.com/v1/")
|
||||||
.CreateFactory();
|
.CreateFactory();
|
||||||
|
|
||||||
SkyHookTvdb = new HttpRequestBuilder("http://skyhook.sonarr.tv/v1/tvdb/{route}/{language}/")
|
SkyHookTvdb = new HttpRequestBuilder("http://skyhook.sonarr.tv/v1/tvdb/{route}/{language}/")
|
||||||
.SetSegment("language", "en")
|
.SetSegment("language", "en")
|
||||||
.CreateFactory();
|
.CreateFactory();
|
||||||
|
|
||||||
|
TMDB = new HttpRequestBuilder("https://api.themoviedb.org/3/{route}/{id}{secondaryRoute}")
|
||||||
|
.AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
|
||||||
|
.CreateFactory();
|
||||||
|
|
||||||
|
TMDBSingle = new HttpRequestBuilder("https://api.themoviedb.org/3/{route}")
|
||||||
|
.AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
|
||||||
|
.CreateFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IHttpRequestBuilderFactory Services { get; private set; }
|
public IHttpRequestBuilderFactory Services { get; private set; }
|
||||||
|
|
||||||
public IHttpRequestBuilderFactory SkyHookTvdb { get; private set; }
|
public IHttpRequestBuilderFactory SkyHookTvdb { get; private set; }
|
||||||
|
public IHttpRequestBuilderFactory TMDB { get; private set; }
|
||||||
|
public IHttpRequestBuilderFactory TMDBSingle { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AppDataFolder = Path.Combine(Environment.GetFolderPath(DATA_SPECIAL_FOLDER, Environment.SpecialFolderOption.None), "NzbDrone");
|
AppDataFolder = Path.Combine(Environment.GetFolderPath(DATA_SPECIAL_FOLDER, Environment.SpecialFolderOption.None), "Radarr");
|
||||||
}
|
}
|
||||||
|
|
||||||
StartUpFolder = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName;
|
StartUpFolder = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName;
|
||||||
|
|
|
@ -13,13 +13,13 @@ namespace NzbDrone.Common.Extensions
|
||||||
private const string NZBDRONE_DB = "nzbdrone.db";
|
private const string NZBDRONE_DB = "nzbdrone.db";
|
||||||
private const string NZBDRONE_LOG_DB = "logs.db";
|
private const string NZBDRONE_LOG_DB = "logs.db";
|
||||||
private const string NLOG_CONFIG_FILE = "nlog.config";
|
private const string NLOG_CONFIG_FILE = "nlog.config";
|
||||||
private const string UPDATE_CLIENT_EXE = "NzbDrone.Update.exe";
|
private const string UPDATE_CLIENT_EXE = "Radarr.Update.exe";
|
||||||
private const string BACKUP_FOLDER = "Backups";
|
private const string BACKUP_FOLDER = "Backups";
|
||||||
|
|
||||||
private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "nzbdrone_update" + Path.DirectorySeparatorChar;
|
private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "radarr_update" + Path.DirectorySeparatorChar;
|
||||||
private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "NzbDrone" + Path.DirectorySeparatorChar;
|
private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "Radarr" + Path.DirectorySeparatorChar;
|
||||||
private static readonly string UPDATE_BACKUP_FOLDER_NAME = "nzbdrone_backup" + Path.DirectorySeparatorChar;
|
private static readonly string UPDATE_BACKUP_FOLDER_NAME = "radarr_backup" + Path.DirectorySeparatorChar;
|
||||||
private static readonly string UPDATE_BACKUP_APPDATA_FOLDER_NAME = "nzbdrone_appdata_backup" + Path.DirectorySeparatorChar;
|
private static readonly string UPDATE_BACKUP_APPDATA_FOLDER_NAME = "radarr_appdata_backup" + Path.DirectorySeparatorChar;
|
||||||
private static readonly string UPDATE_CLIENT_FOLDER_NAME = "NzbDrone.Update" + Path.DirectorySeparatorChar;
|
private static readonly string UPDATE_CLIENT_FOLDER_NAME = "NzbDrone.Update" + Path.DirectorySeparatorChar;
|
||||||
private static readonly string UPDATE_LOG_FOLDER_NAME = "UpdateLogs" + Path.DirectorySeparatorChar;
|
private static readonly string UPDATE_LOG_FOLDER_NAME = "UpdateLogs" + Path.DirectorySeparatorChar;
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@ namespace NzbDrone.Common.Processes
|
||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public const string NZB_DRONE_PROCESS_NAME = "NzbDrone";
|
public const string NZB_DRONE_PROCESS_NAME = "Radarr";
|
||||||
public const string NZB_DRONE_CONSOLE_PROCESS_NAME = "NzbDrone.Console";
|
public const string NZB_DRONE_CONSOLE_PROCESS_NAME = "Radarr.Console";
|
||||||
|
|
||||||
public ProcessProvider(Logger logger)
|
public ProcessProvider(Logger logger)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,4 +9,3 @@ using System.Runtime.InteropServices;
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("b6eaa144-e13b-42e5-a738-c60d89c0f728")]
|
[assembly: Guid("b6eaa144-e13b-42e5-a738-c60d89c0f728")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.0.0.*")]
|
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("sonarr.tv")]
|
[assembly: AssemblyCompany("radarr.tv")]
|
||||||
[assembly: AssemblyProduct("NzbDrone")]
|
[assembly: AssemblyProduct("NzbDrone")]
|
||||||
|
[assembly: AssemblyVersion("0.1.0.*")]
|
||||||
[assembly: AssemblyCopyright("GNU General Public v3")]
|
[assembly: AssemblyCopyright("GNU General Public v3")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace NzbDrone.Common
|
||||||
|
|
||||||
public class ServiceProvider : IServiceProvider
|
public class ServiceProvider : IServiceProvider
|
||||||
{
|
{
|
||||||
public const string NZBDRONE_SERVICE_NAME = "NzbDrone";
|
public const string NZBDRONE_SERVICE_NAME = "Radarr";
|
||||||
|
|
||||||
private readonly IProcessProvider _processProvider;
|
private readonly IProcessProvider _processProvider;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
@ -78,7 +78,7 @@ namespace NzbDrone.Common
|
||||||
serviceInstaller.Context = context;
|
serviceInstaller.Context = context;
|
||||||
serviceInstaller.DisplayName = serviceName;
|
serviceInstaller.DisplayName = serviceName;
|
||||||
serviceInstaller.ServiceName = serviceName;
|
serviceInstaller.ServiceName = serviceName;
|
||||||
serviceInstaller.Description = "NzbDrone Application Server";
|
serviceInstaller.Description = "Radarr Application Server";
|
||||||
serviceInstaller.StartType = ServiceStartMode.Automatic;
|
serviceInstaller.StartType = ServiceStartMode.Automatic;
|
||||||
serviceInstaller.ServicesDependedOn = new[] { "EventLog", "Tcpip", "http" };
|
serviceInstaller.ServicesDependedOn = new[] { "EventLog", "Tcpip", "http" };
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NzbDrone.Host;
|
using Radarr.Host;
|
||||||
|
|
||||||
namespace NzbDrone.Console
|
namespace NzbDrone.Console
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Net.Sockets;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Instrumentation;
|
using NzbDrone.Common.Instrumentation;
|
||||||
using NzbDrone.Host;
|
using Radarr.Host;
|
||||||
|
|
||||||
namespace NzbDrone.Console
|
namespace NzbDrone.Console
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@ namespace NzbDrone.Console
|
||||||
{
|
{
|
||||||
System.Console.WriteLine("");
|
System.Console.WriteLine("");
|
||||||
System.Console.WriteLine("");
|
System.Console.WriteLine("");
|
||||||
Logger.Fatal(exception.Message + ". This can happen if another instance of Sonarr is already running another application is using the same port (default: 8989) or the user has insufficient permissions");
|
Logger.Fatal(exception.Message + ". This can happen if another instance of Radarr is already running another application is using the same port (default: 7878) or the user has insufficient permissions");
|
||||||
System.Console.WriteLine("Press enter to exit...");
|
System.Console.WriteLine("Press enter to exit...");
|
||||||
System.Console.ReadLine();
|
System.Console.ReadLine();
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>NzbDrone.Console</RootNamespace>
|
<RootNamespace>NzbDrone.Console</RootNamespace>
|
||||||
<AssemblyName>NzbDrone.Console</AssemblyName>
|
<AssemblyName>Radarr.Console</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<TargetFrameworkProfile>
|
<TargetFrameworkProfile>
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ApplicationIcon>..\NzbDrone.Host\NzbDrone.ico</ApplicationIcon>
|
<ApplicationIcon>Radarr.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<StartupObject>NzbDrone.Console.ConsoleApp</StartupObject>
|
<StartupObject>NzbDrone.Console.ConsoleApp</StartupObject>
|
||||||
|
@ -139,6 +139,9 @@
|
||||||
</None>
|
</None>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Radarr.ico" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PreBuildEvent>
|
<PreBuildEvent>
|
||||||
|
|
|
@ -7,5 +7,3 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
[assembly: AssemblyTitle("NzbDrone.Host")]
|
[assembly: AssemblyTitle("NzbDrone.Host")]
|
||||||
[assembly: Guid("67AADCD9-89AA-4D95-8281-3193740E70E5")]
|
[assembly: Guid("67AADCD9-89AA-4D95-8281-3193740E70E5")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.0.0.*")]
|
|
BIN
src/NzbDrone.Console/Radarr.ico
Normal file
After Width: | Height: | Size: 41 KiB |
|
@ -178,8 +178,9 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
public void should_return_an_empty_list_when_none_are_appproved()
|
public void should_return_an_empty_list_when_none_are_appproved()
|
||||||
{
|
{
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(null, new Rejection("Failure!")));
|
RemoteEpisode ep = null;
|
||||||
decisions.Add(new DownloadDecision(null, new Rejection("Failure!")));
|
decisions.Add(new DownloadDecision(ep, new Rejection("Failure!")));
|
||||||
|
decisions.Add(new DownloadDecision(ep, new Rejection("Failure!")));
|
||||||
|
|
||||||
Subject.GetQualifiedReports(decisions).Should().BeEmpty();
|
Subject.GetQualifiedReports(decisions).Should().BeEmpty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
using Moq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Common.Http;
|
|
||||||
using NzbDrone.Core.Indexers;
|
|
||||||
using NzbDrone.Core.Indexers.BitMeTv;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using FluentAssertions;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.IndexerTests.BitMeTvTests
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class BitMeTvFixture : CoreTest<BitMeTv>
|
|
||||||
{
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
{
|
|
||||||
Subject.Definition = new IndexerDefinition()
|
|
||||||
{
|
|
||||||
Name = "BitMeTV",
|
|
||||||
Settings = new BitMeTvSettings() { Cookie = "uid=123" }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_parse_recent_feed_from_BitMeTv()
|
|
||||||
{
|
|
||||||
var recentFeed = ReadAllText(@"Files/Indexers/BitMeTv/BitMeTv.xml");
|
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
|
||||||
|
|
||||||
var releases = Subject.FetchRecent();
|
|
||||||
|
|
||||||
releases.Should().HaveCount(5);
|
|
||||||
releases.First().Should().BeOfType<TorrentInfo>();
|
|
||||||
|
|
||||||
var torrentInfo = releases.First() as TorrentInfo;
|
|
||||||
|
|
||||||
torrentInfo.Title.Should().Be("Total.Divas.S02E08.HDTV.x264-CRiMSON");
|
|
||||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
|
||||||
torrentInfo.DownloadUrl.Should().Be("http://www.bitmetv.org/download.php/12/Total.Divas.S02E08.HDTV.x264-CRiMSON.torrent");
|
|
||||||
torrentInfo.InfoUrl.Should().BeNullOrEmpty();
|
|
||||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
|
||||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
|
||||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/05/13 17:04:29"));
|
|
||||||
torrentInfo.Size.Should().Be(395009065);
|
|
||||||
torrentInfo.InfoHash.Should().Be(null);
|
|
||||||
torrentInfo.MagnetUrl.Should().Be(null);
|
|
||||||
torrentInfo.Peers.Should().Be(null);
|
|
||||||
torrentInfo.Seeders.Should().Be(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
using Moq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Common.Http;
|
|
||||||
using NzbDrone.Core.Indexers;
|
|
||||||
using NzbDrone.Core.Indexers.BroadcastheNet;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
using NzbDrone.Test.Common;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using FluentAssertions;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.IndexerTests.BroadcastheNetTests
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class BroadcastheNetFixture : CoreTest<BroadcastheNet>
|
|
||||||
{
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
{
|
|
||||||
Subject.Definition = new IndexerDefinition()
|
|
||||||
{
|
|
||||||
Name = "BroadcastheNet",
|
|
||||||
Settings = new BroadcastheNetSettings() { ApiKey = "abc", BaseUrl = "https://api.btnapps.net/" }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_parse_recent_feed_from_BroadcastheNet()
|
|
||||||
{
|
|
||||||
var recentFeed = ReadAllText(@"Files/Indexers/BroadcastheNet/RecentFeed.json");
|
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
|
||||||
|
|
||||||
var releases = Subject.FetchRecent();
|
|
||||||
|
|
||||||
releases.Should().HaveCount(2);
|
|
||||||
releases.First().Should().BeOfType<TorrentInfo>();
|
|
||||||
|
|
||||||
var torrentInfo = releases.First() as TorrentInfo;
|
|
||||||
|
|
||||||
torrentInfo.Guid.Should().Be("BTN-123");
|
|
||||||
torrentInfo.Title.Should().Be("Jimmy.Kimmel.2014.09.15.Jane.Fonda.HDTV.x264-aAF");
|
|
||||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
|
||||||
torrentInfo.DownloadUrl.Should().Be("https://broadcasthe.net/torrents.php?action=download&id=123&authkey=123&torrent_pass=123");
|
|
||||||
torrentInfo.InfoUrl.Should().Be("https://broadcasthe.net/torrents.php?id=237457&torrentid=123");
|
|
||||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
|
||||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
|
||||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/09/16 21:15:33"));
|
|
||||||
torrentInfo.Size.Should().Be(505099926);
|
|
||||||
torrentInfo.InfoHash.Should().Be("123");
|
|
||||||
torrentInfo.TvdbId.Should().Be(71998);
|
|
||||||
torrentInfo.TvRageId.Should().Be(4055);
|
|
||||||
torrentInfo.MagnetUrl.Should().BeNullOrEmpty();
|
|
||||||
torrentInfo.Peers.Should().Be(40+9);
|
|
||||||
torrentInfo.Seeders.Should().Be(40);
|
|
||||||
|
|
||||||
torrentInfo.Origin.Should().Be("Scene");
|
|
||||||
torrentInfo.Source.Should().Be("HDTV");
|
|
||||||
torrentInfo.Container.Should().Be("MP4");
|
|
||||||
torrentInfo.Codec.Should().Be("x264");
|
|
||||||
torrentInfo.Resolution.Should().Be("SD");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void VerifyBackOff()
|
|
||||||
{
|
|
||||||
Mocker.GetMock<IIndexerStatusService>()
|
|
||||||
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Once());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_back_off_on_bad_request()
|
|
||||||
{
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.BadRequest));
|
|
||||||
|
|
||||||
var results = Subject.FetchRecent();
|
|
||||||
|
|
||||||
results.Should().BeEmpty();
|
|
||||||
|
|
||||||
VerifyBackOff();
|
|
||||||
|
|
||||||
ExceptionVerification.ExpectedWarns(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_back_off_and_report_api_key_invalid()
|
|
||||||
{
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.Unauthorized));
|
|
||||||
|
|
||||||
var results = Subject.FetchRecent();
|
|
||||||
|
|
||||||
results.Should().BeEmpty();
|
|
||||||
|
|
||||||
VerifyBackOff();
|
|
||||||
|
|
||||||
ExceptionVerification.ExpectedWarns(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_back_off_on_unknown_method()
|
|
||||||
{
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.NotFound));
|
|
||||||
|
|
||||||
var results = Subject.FetchRecent();
|
|
||||||
|
|
||||||
results.Should().BeEmpty();
|
|
||||||
|
|
||||||
VerifyBackOff();
|
|
||||||
|
|
||||||
ExceptionVerification.ExpectedWarns(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_back_off_api_limit_reached()
|
|
||||||
{
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.ServiceUnavailable));
|
|
||||||
|
|
||||||
var results = Subject.FetchRecent();
|
|
||||||
|
|
||||||
results.Should().BeEmpty();
|
|
||||||
|
|
||||||
VerifyBackOff();
|
|
||||||
|
|
||||||
ExceptionVerification.ExpectedWarns(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_replace_https_http_as_needed()
|
|
||||||
{
|
|
||||||
var recentFeed = ReadAllText(@"Files/Indexers/BroadcastheNet/RecentFeed.json");
|
|
||||||
|
|
||||||
(Subject.Definition.Settings as BroadcastheNetSettings).BaseUrl = "http://api.btnapps.net/";
|
|
||||||
|
|
||||||
recentFeed = recentFeed.Replace("http:", "https:");
|
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
|
||||||
|
|
||||||
var releases = Subject.FetchRecent();
|
|
||||||
|
|
||||||
releases.Should().HaveCount(2);
|
|
||||||
releases.First().Should().BeOfType<TorrentInfo>();
|
|
||||||
|
|
||||||
var torrentInfo = releases.First() as TorrentInfo;
|
|
||||||
|
|
||||||
torrentInfo.DownloadUrl.Should().Be("http://broadcasthe.net/torrents.php?action=download&id=123&authkey=123&torrent_pass=123");
|
|
||||||
torrentInfo.InfoUrl.Should().Be("http://broadcasthe.net/torrents.php?id=237457&torrentid=123");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
using Moq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Common.Http;
|
|
||||||
using NzbDrone.Core.Indexers;
|
|
||||||
using NzbDrone.Core.Indexers.Torrentleech;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using FluentAssertions;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.IndexerTests.TorrentleechTests
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class TorrentleechFixture : CoreTest<Torrentleech>
|
|
||||||
{
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
{
|
|
||||||
Subject.Definition = new IndexerDefinition()
|
|
||||||
{
|
|
||||||
Name = "Torrentleech",
|
|
||||||
Settings = new TorrentleechSettings()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_parse_recent_feed_from_Torrentleech()
|
|
||||||
{
|
|
||||||
var recentFeed = ReadAllText(@"Files/Indexers/Torrentleech/Torrentleech.xml");
|
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
|
||||||
|
|
||||||
var releases = Subject.FetchRecent();
|
|
||||||
|
|
||||||
releases.Should().HaveCount(5);
|
|
||||||
releases.First().Should().BeOfType<TorrentInfo>();
|
|
||||||
|
|
||||||
var torrentInfo = releases.First() as TorrentInfo;
|
|
||||||
|
|
||||||
torrentInfo.Title.Should().Be("Classic Car Rescue S02E04 720p HDTV x264-C4TV");
|
|
||||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
|
||||||
torrentInfo.DownloadUrl.Should().Be("http://www.torrentleech.org/rss/download/513575/1234/Classic.Car.Rescue.S02E04.720p.HDTV.x264-C4TV.torrent");
|
|
||||||
torrentInfo.InfoUrl.Should().Be("http://www.torrentleech.org/torrent/513575");
|
|
||||||
torrentInfo.CommentUrl.Should().Be("http://www.torrentleech.org/torrent/513575#comments");
|
|
||||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
|
||||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/05/12 19:15:28"));
|
|
||||||
torrentInfo.Size.Should().Be(0);
|
|
||||||
torrentInfo.InfoHash.Should().Be(null);
|
|
||||||
torrentInfo.MagnetUrl.Should().Be(null);
|
|
||||||
torrentInfo.Peers.Should().Be(7+1);
|
|
||||||
torrentInfo.Seeders.Should().Be(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -237,8 +237,6 @@
|
||||||
<Compile Include="IndexerSearchTests\NzbSearchServiceFixture.cs" />
|
<Compile Include="IndexerSearchTests\NzbSearchServiceFixture.cs" />
|
||||||
<Compile Include="IndexerSearchTests\SearchDefinitionFixture.cs" />
|
<Compile Include="IndexerSearchTests\SearchDefinitionFixture.cs" />
|
||||||
<Compile Include="IndexerTests\BasicRssParserFixture.cs" />
|
<Compile Include="IndexerTests\BasicRssParserFixture.cs" />
|
||||||
<Compile Include="IndexerTests\BitMeTvTests\BitMeTvFixture.cs" />
|
|
||||||
<Compile Include="IndexerTests\BroadcastheNetTests\BroadcastheNetFixture.cs" />
|
|
||||||
<Compile Include="IndexerTests\HDBitsTests\HDBitsFixture.cs" />
|
<Compile Include="IndexerTests\HDBitsTests\HDBitsFixture.cs" />
|
||||||
<Compile Include="IndexerTests\IndexerServiceFixture.cs" />
|
<Compile Include="IndexerTests\IndexerServiceFixture.cs" />
|
||||||
<Compile Include="IndexerTests\IndexerStatusServiceFixture.cs" />
|
<Compile Include="IndexerTests\IndexerStatusServiceFixture.cs" />
|
||||||
|
@ -259,7 +257,6 @@
|
||||||
<Compile Include="IndexerTests\IPTorrentsTests\IPTorrentsFixture.cs" />
|
<Compile Include="IndexerTests\IPTorrentsTests\IPTorrentsFixture.cs" />
|
||||||
<Compile Include="IndexerTests\KickassTorrentsTests\KickassTorrentsFixture.cs" />
|
<Compile Include="IndexerTests\KickassTorrentsTests\KickassTorrentsFixture.cs" />
|
||||||
<Compile Include="IndexerTests\NyaaTests\NyaaFixture.cs" />
|
<Compile Include="IndexerTests\NyaaTests\NyaaFixture.cs" />
|
||||||
<Compile Include="IndexerTests\TorrentleechTests\TorrentleechFixture.cs" />
|
|
||||||
<Compile Include="IndexerTests\TorrentRssIndexerTests\TorrentRssIndexerFixture.cs" />
|
<Compile Include="IndexerTests\TorrentRssIndexerTests\TorrentRssIndexerFixture.cs" />
|
||||||
<Compile Include="IndexerTests\TorrentRssIndexerTests\TestTorrentRssIndexer.cs" />
|
<Compile Include="IndexerTests\TorrentRssIndexerTests\TestTorrentRssIndexer.cs" />
|
||||||
<Compile Include="IndexerTests\WomblesTests\WomblesFixture.cs" />
|
<Compile Include="IndexerTests\WomblesTests\WomblesFixture.cs" />
|
||||||
|
|
|
@ -25,6 +25,4 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
[assembly: Guid("699aed1b-015e-4f0d-9c81-d5557b05d260")]
|
[assembly: Guid("699aed1b-015e-4f0d-9c81-d5557b05d260")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.0.0.*")]
|
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("NzbDrone.Core")]
|
[assembly: InternalsVisibleTo("NzbDrone.Core")]
|
|
@ -59,7 +59,7 @@ namespace NzbDrone.Core.Test.UpdateTests
|
||||||
Mocker.GetMock<IVerifyUpdates>().Setup(c => c.Verify(It.IsAny<UpdatePackage>(), It.IsAny<string>())).Returns(true);
|
Mocker.GetMock<IVerifyUpdates>().Setup(c => c.Verify(It.IsAny<UpdatePackage>(), It.IsAny<string>())).Returns(true);
|
||||||
|
|
||||||
Mocker.GetMock<IProcessProvider>().Setup(c => c.GetCurrentProcess()).Returns(new ProcessInfo { Id = 12 });
|
Mocker.GetMock<IProcessProvider>().Setup(c => c.GetCurrentProcess()).Returns(new ProcessInfo { Id = 12 });
|
||||||
Mocker.GetMock<IRuntimeInfo>().Setup(c => c.ExecutingApplication).Returns(@"C:\Test\NzbDrone.exe");
|
Mocker.GetMock<IRuntimeInfo>().Setup(c => c.ExecutingApplication).Returns(@"C:\Test\Radarr.exe");
|
||||||
|
|
||||||
Mocker.GetMock<IConfigFileProvider>()
|
Mocker.GetMock<IConfigFileProvider>()
|
||||||
.SetupGet(s => s.UpdateAutomatically)
|
.SetupGet(s => s.UpdateAutomatically)
|
||||||
|
|
|
@ -133,7 +133,7 @@ namespace NzbDrone.Core.Configuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Port => GetValueInt("Port", 8989);
|
public int Port => GetValueInt("Port", 7878);
|
||||||
|
|
||||||
public int SslPort => GetValueInt("SslPort", 9898);
|
public int SslPort => GetValueInt("SslPort", 9898);
|
||||||
|
|
||||||
|
@ -161,7 +161,8 @@ namespace NzbDrone.Core.Configuration
|
||||||
|
|
||||||
public bool AnalyticsEnabled => GetValueBoolean("AnalyticsEnabled", true, persist: false);
|
public bool AnalyticsEnabled => GetValueBoolean("AnalyticsEnabled", true, persist: false);
|
||||||
|
|
||||||
public string Branch => GetValue("Branch", "master").ToLowerInvariant();
|
// TODO: Change back to "master" for the first stable release.
|
||||||
|
public string Branch => GetValue("Branch", "develop").ToLowerInvariant();
|
||||||
|
|
||||||
public string LogLevel => GetValue("LogLevel", "Info");
|
public string LogLevel => GetValue("LogLevel", "Info");
|
||||||
|
|
||||||
|
@ -303,12 +304,12 @@ namespace NzbDrone.Core.Configuration
|
||||||
|
|
||||||
if (contents.IsNullOrWhiteSpace())
|
if (contents.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
throw new InvalidConfigFileException($"{_configFile} is empty. Please delete the config file and Sonarr will recreate it.");
|
throw new InvalidConfigFileException($"{_configFile} is empty. Please delete the config file and Radarr will recreate it.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contents.All(char.IsControl))
|
if (contents.All(char.IsControl))
|
||||||
{
|
{
|
||||||
throw new InvalidConfigFileException($"{_configFile} is corrupt. Please delete the config file and Sonarr will recreate it.");
|
throw new InvalidConfigFileException($"{_configFile} is corrupt. Please delete the config file and Radarr will recreate it.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return XDocument.Parse(_diskProvider.ReadAllText(_configFile));
|
return XDocument.Parse(_diskProvider.ReadAllText(_configFile));
|
||||||
|
@ -323,7 +324,7 @@ namespace NzbDrone.Core.Configuration
|
||||||
|
|
||||||
catch (XmlException ex)
|
catch (XmlException ex)
|
||||||
{
|
{
|
||||||
throw new InvalidConfigFileException($"{_configFile} is corrupt is invalid. Please delete the config file and Sonarr will recreate it.", ex);
|
throw new InvalidConfigFileException($"{_configFile} is corrupt is invalid. Please delete the config file and Radarr will recreate it.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,32 @@ namespace NzbDrone.Core.Datastore.Migration
|
||||||
.WithColumn("FirstAired").AsDateTime().Nullable()
|
.WithColumn("FirstAired").AsDateTime().Nullable()
|
||||||
.WithColumn("NextAiring").AsDateTime().Nullable();
|
.WithColumn("NextAiring").AsDateTime().Nullable();
|
||||||
|
|
||||||
|
Create.TableForModel("Movies")
|
||||||
|
.WithColumn("ImdbId").AsString().Unique()
|
||||||
|
.WithColumn("Title").AsString()
|
||||||
|
.WithColumn("TitleSlug").AsString().Unique()
|
||||||
|
.WithColumn("SortTitle").AsString().Nullable()
|
||||||
|
.WithColumn("CleanTitle").AsString()
|
||||||
|
.WithColumn("Status").AsInt32()
|
||||||
|
.WithColumn("Overview").AsString().Nullable()
|
||||||
|
.WithColumn("Images").AsString()
|
||||||
|
.WithColumn("Path").AsString()
|
||||||
|
.WithColumn("Monitored").AsBoolean()
|
||||||
|
.WithColumn("ProfileId").AsInt32()
|
||||||
|
.WithColumn("LastInfoSync").AsDateTime().Nullable()
|
||||||
|
.WithColumn("LastDiskSync").AsDateTime().Nullable()
|
||||||
|
.WithColumn("Runtime").AsInt32()
|
||||||
|
.WithColumn("InCinemas").AsDateTime().Nullable()
|
||||||
|
.WithColumn("Year").AsInt32().Nullable()
|
||||||
|
.WithColumn("Added").AsDateTime().Nullable()
|
||||||
|
.WithColumn("Actors").AsString().Nullable()
|
||||||
|
.WithColumn("Ratings").AsString().Nullable()
|
||||||
|
.WithColumn("Genres").AsString().Nullable()
|
||||||
|
.WithColumn("Tags").AsString().Nullable()
|
||||||
|
.WithColumn("Certification").AsString().Nullable()
|
||||||
|
.WithColumn("AddOptions").AsString().Nullable();
|
||||||
|
|
||||||
|
|
||||||
Create.TableForModel("Seasons")
|
Create.TableForModel("Seasons")
|
||||||
.WithColumn("SeriesId").AsInt32()
|
.WithColumn("SeriesId").AsInt32()
|
||||||
.WithColumn("SeasonNumber").AsInt32()
|
.WithColumn("SeasonNumber").AsInt32()
|
||||||
|
@ -79,7 +105,8 @@ namespace NzbDrone.Core.Datastore.Migration
|
||||||
.WithColumn("Quality").AsString()
|
.WithColumn("Quality").AsString()
|
||||||
.WithColumn("Indexer").AsString()
|
.WithColumn("Indexer").AsString()
|
||||||
.WithColumn("NzbInfoUrl").AsString().Nullable()
|
.WithColumn("NzbInfoUrl").AsString().Nullable()
|
||||||
.WithColumn("ReleaseGroup").AsString().Nullable();
|
.WithColumn("ReleaseGroup").AsString().Nullable()
|
||||||
|
.WithColumn("MovieId").AsInt32().WithDefaultValue(0);
|
||||||
|
|
||||||
Create.TableForModel("Notifications")
|
Create.TableForModel("Notifications")
|
||||||
.WithColumn("Name").AsString()
|
.WithColumn("Name").AsString()
|
||||||
|
|
|
@ -21,11 +21,12 @@ namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
|
||||||
//Add HeldReleases
|
//Add HeldReleases
|
||||||
Create.TableForModel("PendingReleases")
|
Create.TableForModel("PendingReleases")
|
||||||
.WithColumn("SeriesId").AsInt32()
|
.WithColumn("SeriesId").AsInt32().WithDefaultValue(0)
|
||||||
.WithColumn("Title").AsString()
|
.WithColumn("Title").AsString()
|
||||||
.WithColumn("Added").AsDateTime()
|
.WithColumn("Added").AsDateTime()
|
||||||
.WithColumn("ParsedEpisodeInfo").AsString()
|
.WithColumn("ParsedEpisodeInfo").AsString()
|
||||||
.WithColumn("Release").AsString();
|
.WithColumn("Release").AsString()
|
||||||
|
.WithColumn("MovieId").AsInt32().WithDefaultValue(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using Marr.Data.Mapping;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Datastore.Extensions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(104)]
|
||||||
|
public class add_moviefiles_table : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Create.TableForModel("MovieFiles")
|
||||||
|
.WithColumn("MovieId").AsInt32()
|
||||||
|
.WithColumn("Path").AsString().Unique()
|
||||||
|
.WithColumn("Quality").AsString()
|
||||||
|
.WithColumn("Size").AsInt64()
|
||||||
|
.WithColumn("DateAdded").AsDateTime()
|
||||||
|
.WithColumn("SceneName").AsString().Nullable()
|
||||||
|
.WithColumn("MediaInfo").AsString().Nullable()
|
||||||
|
.WithColumn("ReleaseGroup").AsString().Nullable()
|
||||||
|
.WithColumn("RelativePath").AsString().Nullable();
|
||||||
|
|
||||||
|
Alter.Table("Movies").AddColumn("MovieFileId").AsInt32().WithDefaultValue(0);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(105)]
|
||||||
|
public class fix_history_movieId : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("History")
|
||||||
|
.AddColumn("MovieId").AsInt32().WithDefaultValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
src/NzbDrone.Core/Datastore/Migration/106_add_tmdb_stuff.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(106)]
|
||||||
|
public class add_tmdb_stuff : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("Movies")
|
||||||
|
.AddColumn("TmdbId").AsInt32().WithDefaultValue(0);
|
||||||
|
Alter.Table("Movies")
|
||||||
|
.AddColumn("Website").AsString().Nullable();
|
||||||
|
Alter.Table("Movies")
|
||||||
|
.AlterColumn("ImdbId").AsString().Nullable();
|
||||||
|
Alter.Table("Movies")
|
||||||
|
.AddColumn("AlternativeTitles").AsString().Nullable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
src/NzbDrone.Core/Datastore/Migration/107_fix_movie_files.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(107)]
|
||||||
|
public class fix_movie_files : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("MovieFiles").AlterColumn("Path").AsString().Nullable(); //Should be deleted, but to much work, ¯\_(ツ)_/¯
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(108)]
|
||||||
|
public class update_schedule_intervale : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("ScheduledTasks").AlterColumn("Interval").AsDouble();
|
||||||
|
Execute.Sql("UPDATE ScheduledTasks SET Interval=0.25 WHERE TypeName='NzbDrone.Core.Download.CheckForFinishedDownloadCommand'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(109)]
|
||||||
|
public class add_movie_formats_to_naming_config : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("NamingConfig").AddColumn("StandardMovieFormat").AsString().Nullable();
|
||||||
|
Alter.Table("NamingConfig").AddColumn("MovieFolderFormat").AsString().Nullable();
|
||||||
|
|
||||||
|
Execute.WithConnection(ConvertConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConvertConfig(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
|
||||||
|
using (IDbCommand namingConfigCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
namingConfigCmd.Transaction = tran;
|
||||||
|
namingConfigCmd.CommandText = @"SELECT * FROM NamingConfig LIMIT 1";
|
||||||
|
using (IDataReader namingConfigReader = namingConfigCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
|
||||||
|
while (namingConfigReader.Read())
|
||||||
|
{
|
||||||
|
// Output Settings
|
||||||
|
var movieTitlePattern = "";
|
||||||
|
var movieYearPattern = "({Release Year})";
|
||||||
|
var qualityFormat = "[{Quality Title}]";
|
||||||
|
|
||||||
|
movieTitlePattern = "{Movie Title}";
|
||||||
|
|
||||||
|
var standardMovieFormat = string.Format("{0} {1} {2}", movieTitlePattern,
|
||||||
|
movieYearPattern,
|
||||||
|
qualityFormat);
|
||||||
|
|
||||||
|
var movieFolderFormat = string.Format("{0} {1}", movieTitlePattern, movieYearPattern);
|
||||||
|
|
||||||
|
|
||||||
|
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
var text = string.Format("UPDATE NamingConfig " +
|
||||||
|
"SET StandardMovieFormat = '{0}', " +
|
||||||
|
"MovieFolderFormat = '{1}'",
|
||||||
|
standardMovieFormat,
|
||||||
|
movieFolderFormat);
|
||||||
|
|
||||||
|
updateCmd.Transaction = tran;
|
||||||
|
updateCmd.CommandText = text;
|
||||||
|
updateCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(110)]
|
||||||
|
public class add_phyiscal_release : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("Movies").AddColumn("PhysicalRelease").AsDateTime().Nullable();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
14
src/NzbDrone.Core/Datastore/Migration/111_remove_bitmetv.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(111)]
|
||||||
|
public class remove_bitmetv : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Delete.FromTable("Indexers").Row(new { Implementation = "BitMeTv" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(112)]
|
||||||
|
public class remove_torrentleech : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Delete.FromTable("Indexers").Row(new { Implementation = "Torrentleech" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(113)]
|
||||||
|
public class remove_broadcasthenet : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Delete.FromTable("Indexers").Row(new { Implementation = "BroadcastheNet" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,7 +60,6 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||||
|
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
|
|
||||||
_announcer.ElapsedTime(sw.Elapsed);
|
_announcer.ElapsedTime(sw.Elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,8 @@ namespace NzbDrone.Core.Datastore
|
||||||
.Relationship()
|
.Relationship()
|
||||||
.HasOne(s => s.Profile, s => s.ProfileId);
|
.HasOne(s => s.Profile, s => s.ProfileId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles")
|
Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles")
|
||||||
.Ignore(f => f.Path)
|
.Ignore(f => f.Path)
|
||||||
.Relationships.AutoMapICollectionOrComplexProperties()
|
.Relationships.AutoMapICollectionOrComplexProperties()
|
||||||
|
@ -84,6 +86,21 @@ namespace NzbDrone.Core.Datastore
|
||||||
query: (db, parent) => db.Query<Episode>().Where(c => c.EpisodeFileId == parent.Id).ToList())
|
query: (db, parent) => db.Query<Episode>().Where(c => c.EpisodeFileId == parent.Id).ToList())
|
||||||
.HasOne(file => file.Series, file => file.SeriesId);
|
.HasOne(file => file.Series, file => file.SeriesId);
|
||||||
|
|
||||||
|
Mapper.Entity<MovieFile>().RegisterModel("MovieFiles")
|
||||||
|
.Ignore(f => f.Path)
|
||||||
|
.Relationships.AutoMapICollectionOrComplexProperties()
|
||||||
|
.For("Movie")
|
||||||
|
.LazyLoad(condition: parent => parent.Id > 0,
|
||||||
|
query: (db, parent) => db.Query<Movie>().Where(c => c.MovieFileId == parent.Id).ToList())
|
||||||
|
.HasOne(file => file.Movie, file => file.MovieId);
|
||||||
|
|
||||||
|
Mapper.Entity<Movie>().RegisterModel("Movies")
|
||||||
|
.Ignore(s => s.RootFolderPath)
|
||||||
|
.Relationship()
|
||||||
|
.HasOne(s => s.Profile, s => s.ProfileId)
|
||||||
|
.HasOne(m => m.MovieFile, m => m.MovieFileId);
|
||||||
|
|
||||||
|
|
||||||
Mapper.Entity<Episode>().RegisterModel("Episodes")
|
Mapper.Entity<Episode>().RegisterModel("Episodes")
|
||||||
.Ignore(e => e.SeriesTitle)
|
.Ignore(e => e.SeriesTitle)
|
||||||
.Ignore(e => e.Series)
|
.Ignore(e => e.Series)
|
||||||
|
@ -123,6 +140,7 @@ namespace NzbDrone.Core.Datastore
|
||||||
RegisterEmbeddedConverter();
|
RegisterEmbeddedConverter();
|
||||||
RegisterProviderSettingConverter();
|
RegisterProviderSettingConverter();
|
||||||
|
|
||||||
|
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(int), new Int32Converter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(int), new Int32Converter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(double), new DoubleConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(double), new DoubleConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(DateTime), new UtcConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(DateTime), new UtcConverter());
|
||||||
|
|
|
@ -7,6 +7,10 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
public class DownloadDecision
|
public class DownloadDecision
|
||||||
{
|
{
|
||||||
public RemoteEpisode RemoteEpisode { get; private set; }
|
public RemoteEpisode RemoteEpisode { get; private set; }
|
||||||
|
|
||||||
|
public RemoteMovie RemoteMovie { get; private set; }
|
||||||
|
|
||||||
|
public bool IsForMovie = false;
|
||||||
public IEnumerable<Rejection> Rejections { get; private set; }
|
public IEnumerable<Rejection> Rejections { get; private set; }
|
||||||
|
|
||||||
public bool Approved => !Rejections.Any();
|
public bool Approved => !Rejections.Any();
|
||||||
|
@ -30,6 +34,23 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
public DownloadDecision(RemoteEpisode episode, params Rejection[] rejections)
|
public DownloadDecision(RemoteEpisode episode, params Rejection[] rejections)
|
||||||
{
|
{
|
||||||
RemoteEpisode = episode;
|
RemoteEpisode = episode;
|
||||||
|
RemoteMovie = new RemoteMovie
|
||||||
|
{
|
||||||
|
Release = episode.Release,
|
||||||
|
ParsedEpisodeInfo = episode.ParsedEpisodeInfo
|
||||||
|
};
|
||||||
|
Rejections = rejections.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownloadDecision(RemoteMovie movie, params Rejection[] rejections)
|
||||||
|
{
|
||||||
|
RemoteMovie = movie;
|
||||||
|
RemoteEpisode = new RemoteEpisode
|
||||||
|
{
|
||||||
|
Release = movie.Release,
|
||||||
|
ParsedEpisodeInfo = movie.ParsedEpisodeInfo
|
||||||
|
};
|
||||||
|
IsForMovie = true;
|
||||||
Rejections = rejections.ToList();
|
Rejections = rejections.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,92 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
|
|
||||||
public List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase)
|
public List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase)
|
||||||
{
|
{
|
||||||
|
if (searchCriteriaBase.Movie != null)
|
||||||
|
{
|
||||||
|
return GetMovieDecisions(reports, searchCriteriaBase).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
return GetDecisions(reports, searchCriteriaBase).ToList();
|
return GetDecisions(reports, searchCriteriaBase).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<DownloadDecision> GetMovieDecisions(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteria = null)
|
||||||
|
{
|
||||||
|
if (reports.Any())
|
||||||
|
{
|
||||||
|
_logger.ProgressInfo("Processing {0} releases", reports.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.ProgressInfo("No results found");
|
||||||
|
}
|
||||||
|
|
||||||
|
var reportNumber = 1;
|
||||||
|
|
||||||
|
foreach (var report in reports)
|
||||||
|
{
|
||||||
|
DownloadDecision decision = null;
|
||||||
|
_logger.ProgressTrace("Processing release {0}/{1}", reportNumber, reports.Count);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var parsedEpisodeInfo = Parser.Parser.ParseMovieTitle(report.Title);
|
||||||
|
|
||||||
|
if (parsedEpisodeInfo != null && !parsedEpisodeInfo.MovieTitle.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
RemoteMovie remoteEpisode = _parsingService.Map(parsedEpisodeInfo, "", searchCriteria);
|
||||||
|
remoteEpisode.Release = report;
|
||||||
|
|
||||||
|
if (remoteEpisode.Movie == null)
|
||||||
|
{
|
||||||
|
//remoteEpisode.DownloadAllowed = true; //Fuck you :)
|
||||||
|
//decision = GetDecisionForReport(remoteEpisode, searchCriteria);
|
||||||
|
decision = new DownloadDecision(remoteEpisode, new Rejection("Unknown release. Movie not Found."));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (parsedEpisodeInfo.Quality.HardcodedSubs.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
remoteEpisode.DownloadAllowed = true;
|
||||||
|
decision = new DownloadDecision(remoteEpisode, new Rejection("Hardcoded subs found: " + parsedEpisodeInfo.Quality.HardcodedSubs));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remoteEpisode.DownloadAllowed = true;
|
||||||
|
decision = GetDecisionForReport(remoteEpisode, searchCriteria);
|
||||||
|
//decision = new DownloadDecision(remoteEpisode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(e, "Couldn't process release.");
|
||||||
|
|
||||||
|
var remoteEpisode = new RemoteEpisode { Release = report };
|
||||||
|
decision = new DownloadDecision(remoteEpisode, new Rejection("Unexpected error processing release"));
|
||||||
|
}
|
||||||
|
|
||||||
|
reportNumber++;
|
||||||
|
|
||||||
|
if (decision != null)
|
||||||
|
{
|
||||||
|
if (decision.Rejections.Any())
|
||||||
|
{
|
||||||
|
_logger.Debug("Release rejected for the following reasons: {0}", string.Join(", ", decision.Rejections));
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Debug("Release accepted");
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return decision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private IEnumerable<DownloadDecision> GetDecisions(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteria = null)
|
private IEnumerable<DownloadDecision> GetDecisions(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteria = null)
|
||||||
{
|
{
|
||||||
if (reports.Any())
|
if (reports.Any())
|
||||||
|
@ -80,7 +163,9 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
|
|
||||||
if (remoteEpisode.Series == null)
|
if (remoteEpisode.Series == null)
|
||||||
{
|
{
|
||||||
decision = new DownloadDecision(remoteEpisode, new Rejection("Unknown Series"));
|
//remoteEpisode.DownloadAllowed = true; //Fuck you :)
|
||||||
|
//decision = GetDecisionForReport(remoteEpisode, searchCriteria);
|
||||||
|
decision = new DownloadDecision(remoteEpisode, new Rejection("Unknown release. Series not Found."));
|
||||||
}
|
}
|
||||||
else if (remoteEpisode.Episodes.Empty())
|
else if (remoteEpisode.Episodes.Empty())
|
||||||
{
|
{
|
||||||
|
@ -120,6 +205,14 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DownloadDecision GetDecisionForReport(RemoteMovie remoteEpisode, SearchCriteriaBase searchCriteria = null)
|
||||||
|
{
|
||||||
|
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria))
|
||||||
|
.Where(c => c != null);
|
||||||
|
|
||||||
|
return new DownloadDecision(remoteEpisode, reasons.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria = null)
|
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria = null)
|
||||||
{
|
{
|
||||||
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria))
|
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria))
|
||||||
|
@ -143,8 +236,36 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
e.Data.Add("report", remoteEpisode.Release.ToJson());
|
e.Data.Add("report", remoteEpisode.Release.ToJson());
|
||||||
e.Data.Add("parsed", remoteEpisode.ParsedEpisodeInfo.ToJson());
|
e.Data.Add("parsed", remoteEpisode.ParsedEpisodeInfo.ToJson());
|
||||||
_logger.Error(e, "Couldn't evaluate decision on " + remoteEpisode.Release.Title);
|
_logger.Error(e, "Couldn't evaluate decision on " + remoteEpisode.Release.Title + ", with spec: " + spec.GetType().Name);
|
||||||
return new Rejection(string.Format("{0}: {1}", spec.GetType().Name, e.Message));
|
//return new Rejection(string.Format("{0}: {1}", spec.GetType().Name, e.Message));//TODO UPDATE SPECS!
|
||||||
|
//return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rejection EvaluateSpec(IDecisionEngineSpecification spec, RemoteMovie remoteEpisode, SearchCriteriaBase searchCriteriaBase = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = spec.IsSatisfiedBy(remoteEpisode, searchCriteriaBase);
|
||||||
|
|
||||||
|
if (!result.Accepted)
|
||||||
|
{
|
||||||
|
return new Rejection(result.Reason, spec.Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NotImplementedException e)
|
||||||
|
{
|
||||||
|
_logger.Info("Spec " + spec.GetType().Name + " does not care about movies.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.Data.Add("report", remoteEpisode.Release.ToJson());
|
||||||
|
e.Data.Add("parsed", remoteEpisode.ParsedEpisodeInfo.ToJson());
|
||||||
|
_logger.Error(e, "Couldn't evaluate decision on " + remoteEpisode.Release.Title + ", with spec: " + spec.GetType().Name);
|
||||||
|
return new Rejection(string.Format("{0}: {1}", spec.GetType().Name, e.Message));//TODO UPDATE SPECS!
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
public interface IPrioritizeDownloadDecision
|
public interface IPrioritizeDownloadDecision
|
||||||
{
|
{
|
||||||
List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions);
|
List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions);
|
||||||
|
List<DownloadDecision> PrioritizeDecisionsForMovies(List<DownloadDecision> decisions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision
|
public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision
|
||||||
|
@ -29,5 +30,17 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
.Union(decisions.Where(c => c.RemoteEpisode.Series == null))
|
.Union(decisions.Where(c => c.RemoteEpisode.Series == null))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<DownloadDecision> PrioritizeDecisionsForMovies(List<DownloadDecision> decisions)
|
||||||
|
{
|
||||||
|
return decisions.Where(c => c.RemoteMovie.Movie != null)
|
||||||
|
/*.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) =>
|
||||||
|
{
|
||||||
|
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
|
||||||
|
})
|
||||||
|
.SelectMany(c => c)*/
|
||||||
|
.Union(decisions.Where(c => c.RemoteMovie.Movie == null))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,5 +8,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
RejectionType Type { get; }
|
RejectionType Type { get; }
|
||||||
|
|
||||||
Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria);
|
Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria);
|
||||||
|
|
||||||
|
Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,5 +107,58 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger.Debug("Item: {0}, meets size constraints.", subject);
|
_logger.Debug("Item: {0}, meets size constraints.", subject);
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||||
|
{
|
||||||
|
_logger.Debug("Beginning size check for: {0}", subject);
|
||||||
|
|
||||||
|
var quality = subject.ParsedMovieInfo.Quality.Quality;
|
||||||
|
|
||||||
|
if (subject.Release.Size == 0)
|
||||||
|
{
|
||||||
|
_logger.Debug("Release has unknown size, skipping size check.");
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
var qualityDefinition = _qualityDefinitionService.Get(quality);
|
||||||
|
if (qualityDefinition.MinSize.HasValue)
|
||||||
|
{
|
||||||
|
var minSize = qualityDefinition.MinSize.Value.Megabytes();
|
||||||
|
|
||||||
|
//Multiply maxSize by Series.Runtime
|
||||||
|
minSize = minSize * subject.Movie.Runtime;
|
||||||
|
|
||||||
|
//If the parsed size is smaller than minSize we don't want it
|
||||||
|
if (subject.Release.Size < minSize)
|
||||||
|
{
|
||||||
|
var runtimeMessage = subject.Movie.Title;
|
||||||
|
|
||||||
|
_logger.Debug("Item: {0}, Size: {1} is smaller than minimum allowed size ({2} bytes for {3}), rejecting.", subject, subject.Release.Size, minSize, runtimeMessage);
|
||||||
|
return Decision.Reject("{0} is smaller than minimum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix(), runtimeMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!qualityDefinition.MaxSize.HasValue || qualityDefinition.MaxSize.Value == 0)
|
||||||
|
{
|
||||||
|
_logger.Debug("Max size is unlimited - skipping check.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var maxSize = qualityDefinition.MaxSize.Value.Megabytes();
|
||||||
|
|
||||||
|
//Multiply maxSize by Series.Runtime
|
||||||
|
maxSize = maxSize * subject.Movie.Runtime;
|
||||||
|
|
||||||
|
//If the parsed size is greater than maxSize we don't want it
|
||||||
|
if (subject.Release.Size > maxSize)
|
||||||
|
{;
|
||||||
|
|
||||||
|
_logger.Debug("Item: {0}, Size: {1} is greater than maximum allowed size ({2} for {3}), rejecting.", subject, subject.Release.Size, maxSize, subject.Movie.Title);
|
||||||
|
return Decision.Reject("{0} is larger than maximum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix(), subject.Movie.Title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Item: {0}, meets size constraints.", subject);
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
@ -55,5 +56,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
|
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ using NLog;
|
||||||
using NzbDrone.Core.Blacklisting;
|
using NzbDrone.Core.Blacklisting;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
|
@ -28,5 +29,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
|
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|