diff --git a/.all-contributorsrc b/.all-contributorsrc index d189704f1..024ee029f 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,3 +1,626 @@ +<<<<<<< HEAD +{ + "files": [ + "README.md" + ], + "imageSize": 100, + "commit": false, + "contributors": [ + { + "login": "pawangeek", + "name": "Pawan Jain", + "avatar_url": "https://avatars0.githubusercontent.com/u/42181691?v=4", + "profile": "https://github.com/pawangeek", + "contributions": [ + "infra", + "test", + "code" + ] + }, + { + "login": "Sacrezar", + "name": "Thomas S.", + "avatar_url": "https://avatars2.githubusercontent.com/u/38185428?v=4", + "profile": "https://github.com/Sacrezar", + "contributions": [ + "code" + ] + }, + { + "login": "YourFriendlyError", + "name": "YourFriendlyError", + "avatar_url": "https://avatars3.githubusercontent.com/u/41340245?v=4", + "profile": "https://github.com/YourFriendlyError", + "contributions": [ + "code" + ] + }, + { + "login": "SoumyaRanjanNaik", + "name": "Soumya Ranjan Naik", + "avatar_url": "https://avatars3.githubusercontent.com/u/44408204?v=4", + "profile": "https://github.com/SoumyaRanjanNaik", + "contributions": [ + "code" + ] + }, + { + "login": "niccolomarcon", + "name": "NiccolΓ² Marcon", + "avatar_url": "https://avatars1.githubusercontent.com/u/9902267?v=4", + "profile": "http://niccolomarcon.it", + "contributions": [ + "code" + ] + }, + { + "login": "hpnightowl", + "name": "HARSH", + "avatar_url": "https://avatars1.githubusercontent.com/u/48650798?v=4", + "profile": "http://hpnightowl.github.io", + "contributions": [ + "code" + ] + }, + { + "login": "javmarina", + "name": "Javi Marina", + "avatar_url": "https://avatars1.githubusercontent.com/u/2737599?v=4", + "profile": "https://www.linkedin.com/in/javier-marina-miranda-1a12111a0/", + "contributions": [ + "code" + ] + }, + { + "login": "maheshschand", + "name": "Rachakulla Mahesh Sarat Chandra", + "avatar_url": "https://avatars0.githubusercontent.com/u/56237961?v=4", + "profile": "https://github.com/maheshschand", + "contributions": [ + "code" + ] + }, + { + "login": "rkgeekoftheweek", + "name": "Ravi K", + "avatar_url": "https://avatars2.githubusercontent.com/u/50319065?v=4", + "profile": "https://github.com/rkgeekoftheweek", + "contributions": [ + "code" + ] + }, + { + "login": "michalStarski", + "name": "MichaΕ‚ Starski", + "avatar_url": "https://avatars3.githubusercontent.com/u/32843198?v=4", + "profile": "https://github.com/michalStarski", + "contributions": [ + "code" + ] + }, + { + "login": "fieryash", + "name": "Ashtik Mahapatra", + "avatar_url": "https://avatars2.githubusercontent.com/u/48550799?v=4", + "profile": "https://github.com/fieryash", + "contributions": [ + "code" + ] + }, + { + "login": "aayuv17", + "name": "Aayushi Varma", + "avatar_url": "https://avatars0.githubusercontent.com/u/59158445?v=4", + "profile": "https://github.com/aayuv17", + "contributions": [ + "code" + ] + }, + { + "login": "Aakasha01Agarwal", + "name": "Aakash Agarwal", + "avatar_url": "https://avatars0.githubusercontent.com/u/58568036?v=4", + "profile": "https://github.com/Aakasha01Agarwal", + "contributions": [ + "code" + ] + }, + { + "login": "suubh", + "name": "suubh", + "avatar_url": "https://avatars0.githubusercontent.com/u/47265493?v=4", + "profile": "https://www.linkedin.com/in/shubham-singh-356ba5168", + "contributions": [ + "code" + ] + }, + { + "login": "gkydev", + "name": "gkydev", + "avatar_url": "https://avatars3.githubusercontent.com/u/26537245?v=4", + "profile": "https://github.com/gkydev", + "contributions": [ + "code" + ] + }, + { + "login": "parth93QA", + "name": "parthzz", + "avatar_url": "https://avatars1.githubusercontent.com/u/55730488?v=4", + "profile": "https://github.com/parth93QA", + "contributions": [ + "code" + ] + }, + { + "login": "GaganSingh5", + "name": "Gagandeep Singh", + "avatar_url": "https://avatars1.githubusercontent.com/u/32139101?v=4", + "profile": "https://github.com/GaganSingh5", + "contributions": [ + "code" + ] + }, + { + "login": "janethavi", + "name": "Janeth Fernando", + "avatar_url": "https://avatars0.githubusercontent.com/u/35697678?v=4", + "profile": "http://www.linkedin.com/in/janethfernando", + "contributions": [ + "code" + ] + }, + { + "login": "jayaganeshkumar", + "name": "jayaganeshkumar", + "avatar_url": "https://avatars0.githubusercontent.com/u/56192588?v=4", + "profile": "https://jayaganeshkumar.me/", + "contributions": [ + "code" + ] + }, + { + "login": "SaiSrichandra", + "name": "SaiSrichandra", + "avatar_url": "https://avatars1.githubusercontent.com/u/53914157?v=4", + "profile": "https://github.com/SaiSrichandra", + "contributions": [ + "code" + ] + }, + { + "login": "shubhampawar", + "name": "Shubham Pawar", + "avatar_url": "https://avatars1.githubusercontent.com/u/20047900?v=4", + "profile": "https://github.com/shubhampawar", + "contributions": [ + "code" + ] + }, + { + "login": "falguni-k", + "name": "falguni-k", + "avatar_url": "https://avatars3.githubusercontent.com/u/49592710?v=4", + "profile": "https://github.com/falguni-k", + "contributions": [ + "code" + ] + }, + { + "login": "Anustup900", + "name": "Anustup Mukherjee", + "avatar_url": "https://avatars0.githubusercontent.com/u/60361231?v=4", + "profile": "https://www.linkedin.com/in/anustup-mukherjee-26755a198/", + "contributions": [ + "code" + ] + }, + { + "login": "ashkankamyab", + "name": "Ashkan", + "avatar_url": "https://avatars2.githubusercontent.com/u/18688356?v=4", + "profile": "http://ashkankamyab.com", + "contributions": [ + "code" + ] + }, + { + "login": "senguyen1011", + "name": "Sean Nguyen", + "avatar_url": "https://avatars2.githubusercontent.com/u/52718953?v=4", + "profile": "https://github.com/senguyen1011", + "contributions": [ + "code" + ] + }, + { + "login": "abhinand5", + "name": "Abhinand", + "avatar_url": "https://avatars2.githubusercontent.com/u/35622449?v=4", + "profile": "http://findabhinand.com/", + "contributions": [ + "code" + ] + }, + { + "login": "varuntumbe", + "name": "Varun Hegde", + "avatar_url": "https://avatars0.githubusercontent.com/u/44541344?v=4", + "profile": "https://github.com/varuntumbe", + "contributions": [ + "code" + ] + }, + { + "login": "edoardottt", + "name": "gilfoyle97", + "avatar_url": "https://avatars3.githubusercontent.com/u/35783570?v=4", + "profile": "https://www.edoardoottavianelli.it", + "contributions": [ + "code" + ] + }, + { + "login": "Lunaditu", + "name": "Lunaditu", + "avatar_url": "https://avatars3.githubusercontent.com/u/54706346?v=4", + "profile": "https://github.com/Lunaditu", + "contributions": [ + "code" + ] + }, + { + "login": "aolaria", + "name": "Alejandro Olaria", + "avatar_url": "https://avatars3.githubusercontent.com/u/29619252?v=4", + "profile": "https://github.com/aolaria", + "contributions": [ + "code" + ] + }, + { + "login": "fa1l", + "name": "fa1l", + "avatar_url": "https://avatars2.githubusercontent.com/u/19634523?v=4", + "profile": "https://github.com/fa1l", + "contributions": [ + "code", + "infra" + ] + }, + { + "login": "mateuszkowalke", + "name": "Mateusz Kowalke", + "avatar_url": "https://avatars2.githubusercontent.com/u/46397613?v=4", + "profile": "https://github.com/mateuszkowalke", + "contributions": [ + "code" + ] + }, + { + "login": "thevirtualbuddy", + "name": "Sonu Saha", + "avatar_url": "https://avatars1.githubusercontent.com/u/42694653?v=4", + "profile": "https://www.linkedin.com/in/sonu-saha-a97754131/", + "contributions": [ + "code" + ] + }, + { + "login": "DevMahmoud10", + "name": "Mahmoud Ahmed", + "avatar_url": "https://avatars2.githubusercontent.com/u/8964887?v=4", + "profile": "http://www.linkedin.com/in/devmahmoud10/", + "contributions": [ + "code" + ] + }, + { + "login": "Kirkkm", + "name": "Kirk", + "avatar_url": "https://avatars2.githubusercontent.com/u/19214317?v=4", + "profile": "https://github.com/Kirkkm", + "contributions": [ + "code" + ] + }, + { + "login": "DragonGhost7", + "name": "DragonGhost7", + "avatar_url": "https://avatars1.githubusercontent.com/u/42487264?v=4", + "profile": "https://github.com/DragonGhost7", + "contributions": [ + "code" + ] + }, + { + "login": "Kartik-byte", + "name": "Kartik Kumar Thakur", + "avatar_url": "https://avatars0.githubusercontent.com/u/72177299?v=4", + "profile": "https://github.com/Kartik-byte", + "contributions": [ + "infra" + ] + }, + { + "login": "ebsa491", + "name": "Sam Ebison", + "avatar_url": "https://avatars3.githubusercontent.com/u/23361794?v=4", + "profile": "http://samebison.ir", + "contributions": [ + "code" + ] + }, + { + "login": "maxily1", + "name": "Max Iliouchenko", + "avatar_url": "https://avatars1.githubusercontent.com/u/55281456?v=4", + "profile": "https://github.com/maxily1", + "contributions": [ + "code" + ] + }, + { + "login": "corleone77", + "name": "cor77", + "avatar_url": "https://avatars2.githubusercontent.com/u/34139210?v=4", + "profile": "https://corleone77.github.io/", + "contributions": [ + "code" + ] + }, + { + "login": "TheFenrisLycaon", + "name": "Fenris Lycaon", + "avatar_url": "https://avatars1.githubusercontent.com/u/54172306?v=4", + "profile": "https://bit.ly/2ZzPAO4", + "contributions": [ + "code" + ] + }, + { + "login": "LucasVanHaaren", + "name": "vhash", + "avatar_url": "https://avatars0.githubusercontent.com/u/29121316?v=4", + "profile": "https://lucasvanhaaren.github.io/", + "contributions": [ + "code" + ] + }, + { + "login": "sculley", + "name": "Sam Culley", + "avatar_url": "https://avatars1.githubusercontent.com/u/3237705?v=4", + "profile": "https://www.samculley.co.uk", + "contributions": [ + "code" + ] + }, + { + "login": "happyeric77", + "name": "Eric Lee", + "avatar_url": "https://avatars2.githubusercontent.com/u/52155607?v=4", + "profile": "https://github.com/happyeric77", + "contributions": [ + "code" + ] + }, + { + "login": "jaypaliwal1212", + "name": "Jay Paliwal", + "avatar_url": "https://avatars3.githubusercontent.com/u/50298189?v=4", + "profile": "https://github.com/jaypaliwal1212", + "contributions": [ + "code" + ] + }, + { + "login": "am401", + "name": "Andras Marton", + "avatar_url": "https://avatars2.githubusercontent.com/u/54643953?v=4", + "profile": "https://placeonthe.net", + "contributions": [ + "code" + ] + }, + { + "login": "SakshiUppoor", + "name": "Sakshi Uppoor", + "avatar_url": "https://avatars2.githubusercontent.com/u/46474346?v=4", + "profile": "https://github.com/SakshiUppoor", + "contributions": [ + "code" + ] + }, + { + "login": "ferhah", + "name": "Ferdinand Hahmann", + "avatar_url": "https://avatars1.githubusercontent.com/u/13720538?v=4", + "profile": "https://github.com/ferhah", + "contributions": [ + "code" + ] + }, + { + "login": "Ajay-Raj-S", + "name": "Ajay Raj", + "avatar_url": "https://avatars0.githubusercontent.com/u/29999212?v=4", + "profile": "https://github.com/Ajay-Raj-S", + "contributions": [ + "code" + ] + }, + { + "login": "paulopacitti", + "name": "Paulo Pacitti", + "avatar_url": "https://avatars1.githubusercontent.com/u/18006523?v=4", + "profile": "https://paulopacitti.itch.io", + "contributions": [ + "code" + ] + }, + { + "login": "HolgerDoerner", + "name": "Holger DΓΆrner", + "avatar_url": "https://avatars3.githubusercontent.com/u/42909210?v=4", + "profile": "https://github.com/HolgerDoerner", + "contributions": [ + "code" + ] + }, + { + "login": "bunnysworld", + "name": "Akash Dwivedi", + "avatar_url": "https://avatars1.githubusercontent.com/u/42912055?v=4", + "profile": "https://github.com/bunnysworld", + "contributions": [ + "code" + ] + }, + { + "login": "Crowfunder", + "name": "Crowfunder", + "avatar_url": "https://avatars2.githubusercontent.com/u/52300171?v=4", + "profile": "https://github.com/Crowfunder", + "contributions": [ + "code" + ] + }, + { + "login": "egurnick", + "name": "egurnick", + "avatar_url": "https://avatars1.githubusercontent.com/u/49304043?v=4", + "profile": "https://github.com/egurnick", + "contributions": [ + "code" + ] + }, + { + "login": "Rishu20", + "name": "Shushant Rishav", + "avatar_url": "https://avatars2.githubusercontent.com/u/54536673?v=4", + "profile": "http://www.sushantrishav.live", + "contributions": [ + "code" + ] + }, + { + "login": "ShubhamNagure", + "name": "Shubham Nagure", + "avatar_url": "https://avatars2.githubusercontent.com/u/49149160?v=4", + "profile": "https://github.com/ShubhamNagure", + "contributions": [ + "code" + ] + }, + { + "login": "Divyansh-20", + "name": "Divyansh Mishra", + "avatar_url": "https://avatars1.githubusercontent.com/u/65251493?v=4", + "profile": "https://github.com/Divyansh-20", + "contributions": [ + "code" + ] + }, + { + "login": "JenishRudani", + "name": "Jenish Rudani", + "avatar_url": "https://avatars3.githubusercontent.com/u/62238590?v=4", + "profile": "https://github.com/JenishRudani", + "contributions": [ + "code" + ] + }, + { + "login": "m4dummies", + "name": "m4Dummies", + "avatar_url": "https://avatars1.githubusercontent.com/u/67146120?v=4", + "profile": "http://m4dummies@gmail.com", + "contributions": [ + "code" + ] + }, + { + "login": "Sripaad", + "name": "Sripaad srinivasan", + "avatar_url": "https://avatars3.githubusercontent.com/u/27012182?v=4", + "profile": "https://github.com/Sripaad", + "contributions": [ + "code" + ] + }, + { + "login": "harshitashankar", + "name": "harshitashankar", + "avatar_url": "https://avatars0.githubusercontent.com/u/68508399?v=4", + "profile": "https://github.com/harshitashankar", + "contributions": [ + "code" + ] + }, + { + "login": "vivekascoder", + "name": "VivekAsCoder", + "avatar_url": "https://avatars3.githubusercontent.com/u/54495208?v=4", + "profile": "http://vivekascoder.ml", + "contributions": [ + "code" + ] + }, + { + "login": "Vilma-Agalioti", + "name": "Vilma Agalioti-Sgompou", + "avatar_url": "https://avatars1.githubusercontent.com/u/11892851?v=4", + "profile": "https://github.com/Vilma-Agalioti", + "contributions": [ + "code" + ] + }, + { + "login": "Crozzers", + "name": "Crozzers", + "avatar_url": "https://avatars.githubusercontent.com/u/57498990?v=4", + "profile": "https://github.com/Crozzers", + "contributions": [ + "code" + ] + }, + { + "login": "urmil89", + "name": "Urmil89", + "avatar_url": "https://avatars.githubusercontent.com/u/60167367?v=4", + "profile": "https://github.com/urmil89", + "contributions": [ + "code" + ] + }, + { + "login": "pranxv", + "name": "pranxv", + "avatar_url": "https://avatars.githubusercontent.com/u/40822047?v=4", + "profile": "https://github.com/pranxv", + "contributions": [ + "code" + ] + }, + { + "login": "sourabh112", + "name": "sourabh112", + "avatar_url": "https://avatars.githubusercontent.com/u/66176305?v=4", + "profile": "https://github.com/sourabh112", + "contributions": [ + "code" + ] + } + ], + "contributorsPerLine": 7, + "projectName": "Automation-scripts", + "projectOwner": "python-geeks", + "repoType": "github", + "repoHost": "https://github.com", + "skipCi": true +} +======= { "files": [ "README.md" @@ -637,3 +1260,4 @@ "repoHost": "https://github.com", "skipCi": true } +>>>>>>> dacfc8398033c984ec7c2b837def8b2e29e03b03 diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 6a409c75a..03b10ac66 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,27 +1,27 @@ ---- -name: πŸ› Bug Report -about: If something isn't working as expected πŸ€” -title: '' -labels: bug -assignees: 'pawangeek' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Additional context** +--- +name: πŸ› Bug Report +about: If something isn't working as expected πŸ€” +title: '' +labels: bug +assignees: 'pawangeek' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** Add any other context about the problem here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/new-script.md b/.github/ISSUE_TEMPLATE/new-script.md index dc5aacfdb..3ceaf874b 100644 --- a/.github/ISSUE_TEMPLATE/new-script.md +++ b/.github/ISSUE_TEMPLATE/new-script.md @@ -1,24 +1,24 @@ ---- -name: πŸš€ Create a new script -about: I wanna add new script to project -title: '' -labels: good first issue, up-for-grabs -assignees: '' - ---- - -## Script Title - - -**Brief** - - -## Instructions - -- Create a new folder for your script and file/folder name should be appropriate. -- Create a README.md in your folder for program Instructions -- add requirements.txt if needed - -### Programming Language - -- [x] Python - -Happy Coding +--- +name: πŸš€ Create a new script +about: I wanna add new script to project +title: '' +labels: good first issue, up-for-grabs +assignees: '' + +--- + +## Script Title - + +**Brief** - + +## Instructions + +- Create a new folder for your script and file/folder name should be appropriate. +- Create a README.md in your folder for program Instructions +- add requirements.txt if needed + +### Programming Language + +- [x] Python + +Happy Coding diff --git a/.github/ISSUE_TEMPLATE/query.md b/.github/ISSUE_TEMPLATE/query.md index 5a661c83d..49818be97 100644 --- a/.github/ISSUE_TEMPLATE/query.md +++ b/.github/ISSUE_TEMPLATE/query.md @@ -1,18 +1,18 @@ ---- -name: πŸ—£ Ask a Question, Discuss -about: How does X work πŸ€”? I made this! I have an idea... -title: '' -labels: query -assignees: 'pawangeek' - ---- - -## Where you stuck - - -**Frankly ask your question (We're also in learning phase :p )** - - -## What you want to do? - - +--- +name: πŸ—£ Ask a Question, Discuss +about: How does X work πŸ€”? I made this! I have an idea... +title: '' +labels: query +assignees: 'pawangeek' + +--- + +## Where you stuck - + +**Frankly ask your question (We're also in learning phase :p )** + + +## What you want to do? + + ## Any other remark/screenshot etc. \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2e28c839e..f078f2788 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,18 +1,18 @@ -# Pull Request Template - -**script name** - - -**Brief about script** - - -### Issue no.(must) - # - -### Self Check(Tick After Making pull Request) - -- [ ] This issue was assigned to me. -- [x] One Change in one Pull Request -- [ ] My file is in proper folder (Name of folder should be in lowercase with no space in between) -- [x] I am following clean code and Documentation and my code is well linted with flake8. -- [ ] I have added README.md and requirements.txt with my script - +# Pull Request Template + +**script name** - + +**Brief about script** + + +### Issue no.(must) - # + +### Self Check(Tick After Making pull Request) + +- [ ] This issue was assigned to me. +- [x] One Change in one Pull Request +- [ ] My file is in proper folder (Name of folder should be in lowercase with no space in between) +- [x] I am following clean code and Documentation and my code is well linted with flake8. +- [ ] I have added README.md and requirements.txt with my script + If issue was not assigned to you Please don't make a PR. It will marked as invalid. \ No newline at end of file diff --git a/.github/labeler.yml b/.github/labeler.yml index d3c627074..793c932c8 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,3 +1,3 @@ -labels: - 'automerge': +labels: + 'automerge': - '\bdocs\b' \ No newline at end of file diff --git a/.github/stale.yml b/.github/stale.yml index 0bbab2909..0bb9bbe55 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,23 +1,23 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 30 - -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 - -# Issues with these labels will never be considered stale -exemptLabels: - - bug - -# Label to use when marking an issue as stale -staleLabel: wontfix - -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. - -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: > - Please reopen this issue once you commit the changes requested or - make improvements on the code. Thank you for your contributions. +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 30 + +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 + +# Issues with these labels will never be considered stale +exemptLabels: + - bug + +# Label to use when marking an issue as stale +staleLabel: wontfix + +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. + +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: > + Please reopen this issue once you commit the changes requested or + make improvements on the code. Thank you for your contributions. diff --git a/.github/weekly-digest.yml b/.github/weekly-digest.yml index 07c5603f3..6e096fd3e 100644 --- a/.github/weekly-digest.yml +++ b/.github/weekly-digest.yml @@ -1,6 +1,6 @@ -publishDay: sun -canPublishIssues: true -canPublishPullRequests: true -canPublishContributors: true -canPublishStargazers: true +publishDay: sun +canPublishIssues: true +canPublishPullRequests: true +canPublishContributors: true +canPublishStargazers: true canPublishCommits: true \ No newline at end of file diff --git a/.github/workflows/auto_close_empty_issues.yml b/.github/workflows/auto_close_empty_issues.yml index 0e01d1ff5..1e42a86e5 100644 --- a/.github/workflows/auto_close_empty_issues.yml +++ b/.github/workflows/auto_close_empty_issues.yml @@ -1,20 +1,20 @@ -# GitHub Action that uses close-issue auto-close empty issues after they are opened. -# If the issue body text is empty the Action auto-closes it and sends a notification. -# Otherwise if the issue body is not empty, it does nothing and the issue remains open. -# https://github.com/marketplace/actions/close-issue - -name: auto_close_empty_issues -on: - issues: - types: [opened] -jobs: - check-issue-body-not-empty: - runs-on: ubuntu-latest - steps: - - if: github.event.issue.body == 0 - name: Close Issue - uses: peter-evans/close-issue@v1 - with: - comment: | - Issue body must contain content. +# GitHub Action that uses close-issue auto-close empty issues after they are opened. +# If the issue body text is empty the Action auto-closes it and sends a notification. +# Otherwise if the issue body is not empty, it does nothing and the issue remains open. +# https://github.com/marketplace/actions/close-issue + +name: auto_close_empty_issues +on: + issues: + types: [opened] +jobs: + check-issue-body-not-empty: + runs-on: ubuntu-latest + steps: + - if: github.event.issue.body == 0 + name: Close Issue + uses: peter-evans/close-issue@v1 + with: + comment: | + Issue body must contain content. Auto-closing this issue. \ No newline at end of file diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 5b1e282de..e31c5bb26 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -1,26 +1,26 @@ -name: automerge -on: - pull_request: - types: - - labeled - - unlabeled - - synchronize - - opened - - edited - - ready_for_review - - reopened - pull_request_review: - types: - - submitted - check_suite: - types: - - completed - status: {} -jobs: - automerge: - runs-on: ubuntu-latest - steps: - - name: automerge - uses: "pascalgn/automerge-action@v0.12.0" - env: +name: automerge +on: + pull_request: + types: + - labeled + - unlabeled + - synchronize + - opened + - edited + - ready_for_review + - reopened + pull_request_review: + types: + - submitted + check_suite: + types: + - completed + status: {} +jobs: + automerge: + runs-on: ubuntu-latest + steps: + - name: automerge + uses: "pascalgn/automerge-action@v0.12.0" + env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" \ No newline at end of file diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d8c8aec09..233670ca6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,18 +1,18 @@ -name: Flake8Linter -on: [pull_request] - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.8' - - name: Install flake8 - run: | - python -m pip install --upgrade pip - pip install flake8 - - name: Lint with flake8 - run: flake8 . --isolated --exclude=.cache,.venv,.svn,CVS,.bzr,.hg,.git,__pycache__,.tox,**/migrations/** --ignore=E203,W503 --max-line-length=119 +name: Flake8Linter +on: [pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.8' + - name: Install flake8 + run: | + python -m pip install --upgrade pip + pip install flake8 + - name: Lint with flake8 + run: flake8 . --isolated --exclude=.cache,.venv,.svn,CVS,.bzr,.hg,.git,__pycache__,.tox,**/migrations/** --ignore=E203,W503 --max-line-length=119 diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 985f1ca27..558419332 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -1,15 +1,15 @@ -name: SpellCheck -on: [pull_request] -jobs: - codespell: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - run: pip install codespell flake8 - - run: | - SKIP="./.*, ./zip_password_cracker/passwords.txt" - codespell --ignore-words-list=ans,fo,followings,hist,iff,secant,som,tim --skip=$SKIP --quiet-level=2 - - name: Codespell comment - if: ${{ failure() }} - uses: plettich/python_codespell_action@master +name: SpellCheck +on: [pull_request] +jobs: + codespell: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - run: pip install codespell flake8 + - run: | + SKIP="./.*, ./zip_password_cracker/passwords.txt" + codespell --ignore-words-list=ans,fo,followings,hist,iff,secant,som,tim --skip=$SKIP --quiet-level=2 + - name: Codespell comment + if: ${{ failure() }} + uses: plettich/python_codespell_action@master diff --git a/.github/workflows/community.yml b/.github/workflows/community.yml index 039f33699..935812125 100644 --- a/.github/workflows/community.yml +++ b/.github/workflows/community.yml @@ -1,16 +1,16 @@ -name: Community -on: - pull_request_target: - types: [opened] - -jobs: - - labeler: - runs-on: ubuntu-latest - - steps: - - name: Check Labels - id: labeler - uses: jimschubert/labeler-action@v2 - with: +name: Community +on: + pull_request_target: + types: [opened] + +jobs: + + labeler: + runs-on: ubuntu-latest + + steps: + - name: Check Labels + id: labeler + uses: jimschubert/labeler-action@v2 + with: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} \ No newline at end of file diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml index 272823c60..9d9c33f6e 100644 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -1,12 +1,12 @@ -name: Greetings - -on: [pull_request_target] - -jobs: - greeting: - runs-on: ubuntu-latest - steps: - - uses: actions/first-interaction@v1 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" +name: Greetings + +on: [pull_request_target] + +jobs: + greeting: + runs-on: ubuntu-latest + steps: + - uses: actions/first-interaction@v1 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" pr-message: 'Congratulations!! πŸŽ‰ @${{ github.actor }} for making your first PR. We will review the changes soon and merge finally.😊 Do give a star ⭐ meanwhile if you like this project. ' \ No newline at end of file diff --git a/.gitignore b/.gitignore index 56f615af2..b515aaffb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,68 +1,68 @@ - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.pyc -*.pyo -*.pyd -*.local - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg -*.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache/ -.hypothesis/ -coverage.xml - -# IPython Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# virtualenv -venv/ -.venv/ -ENV/ - -# pytest -.pytest_cache/ - -# IDE -.idea/ -.vscode/ - -# macOS + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.pyc +*.pyo +*.pyd +*.local + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache/ +.hypothesis/ +coverage.xml + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# virtualenv +venv/ +.venv/ +ENV/ + +# pytest +.pytest_cache/ + +# IDE +.idea/ +.vscode/ + +# macOS .DS_Store \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index fc2486db5..0686162e7 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,76 +1,76 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at biswajeetsahoo54@gmail.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at biswajeetsahoo54@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0706d9631..bd13f36b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,75 +1,75 @@ -# Contributing to Automation Scripts - -We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: - -- Reporting a bug -- Discussing the current state of the code -- Submitting a fix -- Proposing new features - - -## Steps to contribute - -* Comment on the issue you want to work on. Make sure it's not assigned to someone else. - -## What to contribute - -* Any Pytorch real life implementation -* Should add README.txt to execute, required environment and dataset link -* Compatible old implementations with new fixes -* Add REQUIREMENTS.txt with the your Jupyter notebook - -### Making a PR - -> - Make sure you have been assigned the issue to which you are making a PR. -> - If you make PR before being assigned, It will be labeled `invalid` and closed without merging. - -* Fork the repo and clone it on your machine. -* Add a upstream link to main branch in your cloned repo - ``` - git remote add upstream https://github.com/python-geeks/Automation-scripts.git - ``` -* Keep your cloned repo up to date by pulling from upstream (this will also avoid any merge conflicts while committing new changes) - ``` - git pull upstream main - ``` -* Create your feature branch - ``` - git checkout -b - ``` -* Commit all the changes - ``` - git commit -am "Meaningful commit message" - ``` -* Push the changes for review - ``` - git push origin - ``` -* Create a PR from our repo on Github. - -### Additional Notes - -* Code should be properly commented to ensure it's readability. -* If you've added code that should be tested, add tests as comments. -* Make sure your code properly formatted. -* Issue that pull request! -* use Flake8 for python code - -## Issue suggestions/Bug reporting - -When you are creating an issue, make sure it's not already present. Furthermore, provide a proper description of the changes. If you are suggesting any code improvements, provide through details about the improvements. - -**Great Issue suggestions** tend to have: - -- A quick summary of the changes. -- In case of any bug provide steps to reproduce - - Be specific! - - Give sample code if you can. - - What you expected would happen - - What actually happens - - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) - - -## License - -By contributing, you agree that your contributions will be licensed under its [MIT License](http://choosealicense.com/licenses/mit/). +# Contributing to Automation Scripts + +We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: + +- Reporting a bug +- Discussing the current state of the code +- Submitting a fix +- Proposing new features + + +## Steps to contribute + +* Comment on the issue you want to work on. Make sure it's not assigned to someone else. + +## What to contribute + +* Any Pytorch real life implementation +* Should add README.txt to execute, required environment and dataset link +* Compatible old implementations with new fixes +* Add REQUIREMENTS.txt with the your Jupyter notebook + +### Making a PR + +> - Make sure you have been assigned the issue to which you are making a PR. +> - If you make PR before being assigned, It will be labeled `invalid` and closed without merging. + +* Fork the repo and clone it on your machine. +* Add a upstream link to main branch in your cloned repo + ``` + git remote add upstream https://github.com/python-geeks/Automation-scripts.git + ``` +* Keep your cloned repo up to date by pulling from upstream (this will also avoid any merge conflicts while committing new changes) + ``` + git pull upstream main + ``` +* Create your feature branch + ``` + git checkout -b + ``` +* Commit all the changes + ``` + git commit -am "Meaningful commit message" + ``` +* Push the changes for review + ``` + git push origin + ``` +* Create a PR from our repo on Github. + +### Additional Notes + +* Code should be properly commented to ensure it's readability. +* If you've added code that should be tested, add tests as comments. +* Make sure your code properly formatted. +* Issue that pull request! +* use Flake8 for python code + +## Issue suggestions/Bug reporting + +When you are creating an issue, make sure it's not already present. Furthermore, provide a proper description of the changes. If you are suggesting any code improvements, provide through details about the improvements. + +**Great Issue suggestions** tend to have: + +- A quick summary of the changes. +- In case of any bug provide steps to reproduce + - Be specific! + - Give sample code if you can. + - What you expected would happen + - What actually happens + - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) + + +## License + +By contributing, you agree that your contributions will be licensed under its [MIT License](http://choosealicense.com/licenses/mit/). diff --git a/LICENSE b/LICENSE index 63392c21c..770c5f714 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2020 Pythongeeks - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2020 Pythongeeks + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 936b41921..1f63922b4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,153 @@ +<<<<<<< HEAD +# Automation-scripts + +[![All Contributors](https://img.shields.io/badge/all_contributors-67-orange.svg?style=flat-square)](#contributors-) + + +Do you know anything that can help all to easy our tough life than tell that secret to us and help us to become lazy like Panda + +## Update 1 : +**Thanks for all contributors my panda stopped cycling now πŸ›΄** + +## Update 2 : +**Cheers to all, our panda removed exercise from daily schedule πŸ€Έβ€β™‚οΈ** + +## Update 3 : +**Moving forward we achieve our next goal, now our panda doesn't play any outdoor game anymore πŸŒοΈβ€β™‚οΈ** + +## Update 4: +**Goals of 2020 completed, Panda now hired a maid to clean his house :)** + +And it's okay if you're not aware of process. Kindly raise query by creating pull request (In query template). Here is the link for that how to create a pull request in other's Repo + +[How to create pull request](https://opensource.com/article/19/7/create-pull-request-github) + +### These are my Lazy Panda Goals + +* Goal Achieved - 101/100 + +* Goal 25 - Panda stopped Cycling (Completed) +* Goal 50 - Panda stopped doing Exercise +* Goal 75 - Panda stopped Playing outdoor games +* Goal 100 - Panda hire someone for cleaning house + +**Leave a star => Contribution in arranging Food for panda 😴** + +## How to Contribute πŸ€” + +You can contribute by adding new scripts, improving current scripts or Documentation.Here are some Instructions +before making a Pull Request + +### Here are the steps to Make contribute πŸ‘£ + +- [x] Create an issue for making any change to code. when issue will be approve you can make a change. +- [x] Pull latest change from upstream branch before starting the changing code. +- [x] Add your file in proper folder(lowercase) with README.md in it. Add requirements.txt if needed. +- [x] Please use flake8 linting in your code + +#### Typo fixed/ minor change in docs not marked as contribution. If you're not aware of process kindly raise a query in formal manner :) +## Contributors ✨ + +Thanks goes to these wonderful people 😊 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Pawan Jain

πŸš‡ ⚠️ πŸ’»

Thomas S.

πŸ’»

YourFriendlyError

πŸ’»

Soumya Ranjan Naik

πŸ’»

NiccolΓ² Marcon

πŸ’»

HARSH

πŸ’»

Javi Marina

πŸ’»

Rachakulla Mahesh Sarat Chandra

πŸ’»

Ravi K

πŸ’»

MichaΕ‚ Starski

πŸ’»

Ashtik Mahapatra

πŸ’»

Aayushi Varma

πŸ’»

Aakash Agarwal

πŸ’»

suubh

πŸ’»

gkydev

πŸ’»

parthzz

πŸ’»

Gagandeep Singh

πŸ’»

Janeth Fernando

πŸ’»

jayaganeshkumar

πŸ’»

SaiSrichandra

πŸ’»

Shubham Pawar

πŸ’»

falguni-k

πŸ’»

Anustup Mukherjee

πŸ’»

Ashkan

πŸ’»

Sean Nguyen

πŸ’»

Abhinand

πŸ’»

Varun Hegde

πŸ’»

gilfoyle97

πŸ’»

Lunaditu

πŸ’»

Alejandro Olaria

πŸ’»

fa1l

πŸ’» πŸš‡

Mateusz Kowalke

πŸ’»

Sonu Saha

πŸ’»

Mahmoud Ahmed

πŸ’»

Kirk

πŸ’»

DragonGhost7

πŸ’»

Kartik Kumar Thakur

πŸš‡

Sam Ebison

πŸ’»

Max Iliouchenko

πŸ’»

cor77

πŸ’»

Fenris Lycaon

πŸ’»

vhash

πŸ’»

Sam Culley

πŸ’»

Eric Lee

πŸ’»

Jay Paliwal

πŸ’»

Andras Marton

πŸ’»

Sakshi Uppoor

πŸ’»

Ferdinand Hahmann

πŸ’»

Ajay Raj

πŸ’»

Paulo Pacitti

πŸ’»

Holger DΓΆrner

πŸ’»

Akash Dwivedi

πŸ’»

Crowfunder

πŸ’»

egurnick

πŸ’»

Shushant Rishav

πŸ’»

Shubham Nagure

πŸ’»

Divyansh Mishra

πŸ’»

Jenish Rudani

πŸ’»

m4Dummies

πŸ’»

Sripaad srinivasan

πŸ’»

harshitashankar

πŸ’»

VivekAsCoder

πŸ’»

Vilma Agalioti-Sgompou

πŸ’»

Crozzers

πŸ’»

Urmil89

πŸ’»

pranxv

πŸ’»

sourabh112

πŸ’»
+ + + + + +======= # Automation-scripts [![All Contributors](https://img.shields.io/badge/all_contributors-69-orange.svg?style=flat-square)](#contributors-) @@ -148,3 +298,4 @@ Thanks goes to these wonderful people 😊 +>>>>>>> dacfc8398033c984ec7c2b837def8b2e29e03b03 diff --git a/alarm_clock/AlarmClock.py b/alarm_clock/AlarmClock.py index c7baebae0..79136ddae 100644 --- a/alarm_clock/AlarmClock.py +++ b/alarm_clock/AlarmClock.py @@ -1,21 +1,21 @@ -import time -import datetime -import simpleaudio - - -set_time = input("please enter the time in HH:MM format to set an alarm : ") -while True: - time.sleep(1) - obj = simpleaudio.WaveObject.from_wave_file("./alarm.wav") - current_time = datetime.datetime.now().time().strftime("%H:%M") - curr_l = current_time.split(":") - curr_l = [int(i) for i in curr_l] - set_l = set_time.split(":") - set_l = [int(i) for i in set_l] - print(f"current time : {current_time}") - print(f"alarm time : {set_time}") - if curr_l[0] == set_l[0] and curr_l[1] == set_l[1]: - obj.play() - print("Time to Wake up") - input("Press enter to Stop") - break +import time +import datetime +import simpleaudio + + +set_time = input("please enter the time in HH:MM format to set an alarm : ") +while True: + time.sleep(1) + obj = simpleaudio.WaveObject.from_wave_file("./alarm.wav") + current_time = datetime.datetime.now().time().strftime("%H:%M") + curr_l = current_time.split(":") + curr_l = [int(i) for i in curr_l] + set_l = set_time.split(":") + set_l = [int(i) for i in set_l] + print(f"current time : {current_time}") + print(f"alarm time : {set_time}") + if curr_l[0] == set_l[0] and curr_l[1] == set_l[1]: + obj.play() + print("Time to Wake up") + input("Press enter to Stop") + break diff --git a/alarm_clock/README.md b/alarm_clock/README.md index d11e51521..afbe8c0e1 100644 --- a/alarm_clock/README.md +++ b/alarm_clock/README.md @@ -1,68 +1,68 @@ -# Using AlarmClock script - -## Dependencies : - For Ubuntu based systems please execute the following command to install the required dependencies. - ``` - sudo apt-get install -y python3-dev libasound2-dev - ``` - For other Unix based distros please google the package name. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## Steps to set an alarm : -1. run the script `AlarmClock.py` using python3. - On Unix based systems the command looks like : - ```bash - python3 AlarmClock.py - ``` - or - ```bash - python AlarmClock.py - ``` - -2. After execution of the script you will be prompted to enter the time to set an alarm in HH:MM format. Which looks something as shown below : - ``` - please enter the time in HH:MM format to set an alarm : - ``` - Enter the time on the prompt in __24 HOURS FORMAT__ as shown in the example below : - ``` - please enter the time in HH:MM format to set an alarm : 14:32 - ``` - -3. Then you will get a looping output of the current time and set time on the CLI as shown below : - ``` - please enter the time in HH:MM format to set an alarm : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - current time : 11:48 - alarm time : 14:32 - ``` -4. When the alarm goes off you will __hear a sound__ and get the following lines on the prompt : - ``` - Time to Wake up - Press enter to Stop - ``` -5. Press enter to stop the alarm else the alarm will stop the sound after 33 seconds. - -## NOTE : To change the alarm sound just __replace the alarm.wav with your choice of .wav__ file and __rename it to alarm.wav__. +# Using AlarmClock script + +## Dependencies : + For Ubuntu based systems please execute the following command to install the required dependencies. + ``` + sudo apt-get install -y python3-dev libasound2-dev + ``` + For other Unix based distros please google the package name. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## Steps to set an alarm : +1. run the script `AlarmClock.py` using python3. + On Unix based systems the command looks like : + ```bash + python3 AlarmClock.py + ``` + or + ```bash + python AlarmClock.py + ``` + +2. After execution of the script you will be prompted to enter the time to set an alarm in HH:MM format. Which looks something as shown below : + ``` + please enter the time in HH:MM format to set an alarm : + ``` + Enter the time on the prompt in __24 HOURS FORMAT__ as shown in the example below : + ``` + please enter the time in HH:MM format to set an alarm : 14:32 + ``` + +3. Then you will get a looping output of the current time and set time on the CLI as shown below : + ``` + please enter the time in HH:MM format to set an alarm : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + current time : 11:48 + alarm time : 14:32 + ``` +4. When the alarm goes off you will __hear a sound__ and get the following lines on the prompt : + ``` + Time to Wake up + Press enter to Stop + ``` +5. Press enter to stop the alarm else the alarm will stop the sound after 33 seconds. + +## NOTE : To change the alarm sound just __replace the alarm.wav with your choice of .wav__ file and __rename it to alarm.wav__. diff --git a/alarm_clock/makefile b/alarm_clock/makefile index e78e53c81..7aafa604a 100644 --- a/alarm_clock/makefile +++ b/alarm_clock/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/articles_to_pdf/README.md b/articles_to_pdf/README.md index 25260fe92..c9f36a945 100644 --- a/articles_to_pdf/README.md +++ b/articles_to_pdf/README.md @@ -1,67 +1,67 @@ -# articles_to_pdf - -Convert online articles to PDF. - -## What it does - -There are 2 ways to use this script: - -- Option 1: Perform a search on Medium and export 1 to 10 articles from the search results as pdf -- Option 2: Export a single online article by pasting a direct URL to the article - -## How to use - -### Download browser and driver (Needed if using option 1) -You need to have either Firefox or Chrome installed. You also need the corresponding driver for the browser. - -For Firefox download geckodriver: -https://github.com/mozilla/geckodriver/releases - -For Chrome download chromedriver: -https://chromedriver.chromium.org/downloads - -Place the driver in the same directory as the script. - -### Setup modules - -Python and the following modules must be installed on the computer running this script. -Install the required modules by running this command in the directory of the requirements.txt file: -``` -pip install -r requirements.txt -``` - -### Install wkhtmltopdf -``` -sudo apt-get install wkhtmltopdf -``` - -### Run program - -Run using: -``` -python articles_to_pdf.py -``` - -You will be prompted for your settings. -``` -Enter '1' to search medium or '2' to export a single medium article: -``` - -**For Option 1.** You should type in the search you want to perfom on Medium and the number of articles you want exported to PDF. The number of articles should be between 1 and 10. Example: -``` -Enter search term followed by number of articles between 1 and 10 (e.g "learn python 5"): learn python 5 -``` -In this case "learn python" will be searched on Medium and 5 articles will be exported as PDF. The file name will contain the article titles. - -**For Option 2.** Paste the URL for the article to convert to pdf. Example: -``` -Paste URL to convert to PDF (must begin with 'https://'): https://medium.com/fintechexplained/everything-about-python-from-beginner-to-advance-level-227d52ef32d2 -``` -The article will be exported as PDF in a file called "converted.pdf" - -### Tips for developers - -Using Option 1 runs the browser in headless mode which means the browser GUI is not opened while running the program. -If you want the GUI to open while the script is running do the following: -- If using geckodriver change `firefox_options.headless = True` to `firefox_options.headless = False` +# articles_to_pdf + +Convert online articles to PDF. + +## What it does + +There are 2 ways to use this script: + +- Option 1: Perform a search on Medium and export 1 to 10 articles from the search results as pdf +- Option 2: Export a single online article by pasting a direct URL to the article + +## How to use + +### Download browser and driver (Needed if using option 1) +You need to have either Firefox or Chrome installed. You also need the corresponding driver for the browser. + +For Firefox download geckodriver: +https://github.com/mozilla/geckodriver/releases + +For Chrome download chromedriver: +https://chromedriver.chromium.org/downloads + +Place the driver in the same directory as the script. + +### Setup modules + +Python and the following modules must be installed on the computer running this script. +Install the required modules by running this command in the directory of the requirements.txt file: +``` +pip install -r requirements.txt +``` + +### Install wkhtmltopdf +``` +sudo apt-get install wkhtmltopdf +``` + +### Run program + +Run using: +``` +python articles_to_pdf.py +``` + +You will be prompted for your settings. +``` +Enter '1' to search medium or '2' to export a single medium article: +``` + +**For Option 1.** You should type in the search you want to perfom on Medium and the number of articles you want exported to PDF. The number of articles should be between 1 and 10. Example: +``` +Enter search term followed by number of articles between 1 and 10 (e.g "learn python 5"): learn python 5 +``` +In this case "learn python" will be searched on Medium and 5 articles will be exported as PDF. The file name will contain the article titles. + +**For Option 2.** Paste the URL for the article to convert to pdf. Example: +``` +Paste URL to convert to PDF (must begin with 'https://'): https://medium.com/fintechexplained/everything-about-python-from-beginner-to-advance-level-227d52ef32d2 +``` +The article will be exported as PDF in a file called "converted.pdf" + +### Tips for developers + +Using Option 1 runs the browser in headless mode which means the browser GUI is not opened while running the program. +If you want the GUI to open while the script is running do the following: +- If using geckodriver change `firefox_options.headless = True` to `firefox_options.headless = False` - If using chromedriver change `chrome_options.add_argument('--headless')` to `chrome_options.add_argument('--None')` \ No newline at end of file diff --git a/articles_to_pdf/articles_to_pdf.py b/articles_to_pdf/articles_to_pdf.py index 1793fd017..e4b2b7d0c 100644 --- a/articles_to_pdf/articles_to_pdf.py +++ b/articles_to_pdf/articles_to_pdf.py @@ -1,157 +1,157 @@ -from selenium import webdriver -from selenium.webdriver.firefox.options import Options as Options_firefox -from selenium.webdriver.chrome.options import Options as Options_chrome - -from pathlib import Path -import pdfkit - - -def setup_driver(): - - # use the driver that exists in working directory - chromedriver and geckodriver supported - - find_geckodriver = Path("geckodriver") - find_chromedriver = Path("chromedriver") - - if find_geckodriver.exists(): - driver = 'geckodriver' - print('Using %s' % driver) - PATH_TO_DRIVER = './%s' % driver - - firefox_options = Options_firefox() - - # run in headless mode - firefox_options.headless = True - - # disable cookies to prevent popups - opt = webdriver.FirefoxProfile() - opt.set_preference("network.cookie.cookieBehavior", 2) - - browser = webdriver.Firefox(executable_path=PATH_TO_DRIVER, options=firefox_options, firefox_profile=opt) - - elif find_chromedriver.exists(): - driver = 'chromedriver' - print('Using %s' % driver) - PATH_TO_DRIVER = './%s' % driver - - chrome_options = Options_chrome() - - # run in headless mode - chrome_options.add_argument('--headless') - - # disable cookies to prevent popups - chrome_options.add_experimental_option('prefs', {'profile.default_content_setting_values.cookies': 2}) - - browser = webdriver.Chrome(executable_path=PATH_TO_DRIVER, options=chrome_options) - - else: - print('ERROR: No valid driver found. Only geckodriver or chromedriver is supported!') - exit() - - return browser - - -def scrape_medium(browser, search_term, search_count): - - # perform search of keyword in medium - - browser.get('https://medium.com/search?q=%s' % search_term) - browser.implicitly_wait(10) - - results = browser.find_elements_by_xpath('//a[contains(text(), "Read more")]') - - all_articles = [] - # get the links for all articles and store in list - for each_article in results: - all_articles.append(each_article.get_attribute('href')) - - # go to link of each article and export as PDF - for counter, url in enumerate(all_articles, 1): - print('Exporting article %s/%s: %s' % ((counter), search_count, url)) - - browser.get(url) - browser.implicitly_wait(10) - - # get title - article_title = browser.title - - # get url of page to export - url_to_export = browser.current_url - - # pdf name will contain article title - pdf = 'Medium-%s.pdf' % article_title - pdf = pdf.replace(' ', '-') - - # export pdf - quiet_mode = {'quiet': ''} - pdfkit.from_url(url_to_export, pdf, options=quiet_mode) - - # stop when we reach specified search count - if (counter == int(search_count)): - print('Complete. %s medium articles exported to PDF.' % search_count) - browser.close() - return - - -def process_option_1(): - - # get user settings - user_input = input('Enter search term followed by number of articles between 1 and 10 (e.g "learn python 5"): ') - user_input = user_input.split(' ') - - # last entry should be a number - try: - search_count = int(user_input[-1]) - except ValueError: - print('ERROR: Invalid input. The last entry must end with a number!') - return - - # remove number from list - user_input.pop() - - # join strings to load the phrase to search - search_term = ' ' - for each_word in user_input: - search_term = search_term + each_word + ' ' - - browser = setup_driver() - scrape_medium(browser, search_term, search_count) - exit() - - -def process_option_2(): - - # export a single article from the URL - url = input("Paste URL to convert to PDF (must begin with 'https://'): ") - - print('Converting to PDF...') - quiet_mode = {'quiet': ''} - pdfkit.from_url(url, 'converted.pdf', options=quiet_mode) - print('Complete. See "converted.pdf"') - exit() - - -def program_run(): - - while True: - # get user option - option = input("Enter '1' to search medium or '2' to export a single medium article: ") - - if option == '1': - process_option_1() - - elif option == '2': - process_option_2() - - elif option == 'x': - exit() - - else: - print("Invalid option. Try again! Or enter x to exit") - continue - pass - - -if __name__ == "__main__": - program_run() - pass +from selenium import webdriver +from selenium.webdriver.firefox.options import Options as Options_firefox +from selenium.webdriver.chrome.options import Options as Options_chrome + +from pathlib import Path +import pdfkit + + +def setup_driver(): + + # use the driver that exists in working directory - chromedriver and geckodriver supported + + find_geckodriver = Path("geckodriver") + find_chromedriver = Path("chromedriver") + + if find_geckodriver.exists(): + driver = 'geckodriver' + print('Using %s' % driver) + PATH_TO_DRIVER = './%s' % driver + + firefox_options = Options_firefox() + + # run in headless mode + firefox_options.headless = True + + # disable cookies to prevent popups + opt = webdriver.FirefoxProfile() + opt.set_preference("network.cookie.cookieBehavior", 2) + + browser = webdriver.Firefox(executable_path=PATH_TO_DRIVER, options=firefox_options, firefox_profile=opt) + + elif find_chromedriver.exists(): + driver = 'chromedriver' + print('Using %s' % driver) + PATH_TO_DRIVER = './%s' % driver + + chrome_options = Options_chrome() + + # run in headless mode + chrome_options.add_argument('--headless') + + # disable cookies to prevent popups + chrome_options.add_experimental_option('prefs', {'profile.default_content_setting_values.cookies': 2}) + + browser = webdriver.Chrome(executable_path=PATH_TO_DRIVER, options=chrome_options) + + else: + print('ERROR: No valid driver found. Only geckodriver or chromedriver is supported!') + exit() + + return browser + + +def scrape_medium(browser, search_term, search_count): + + # perform search of keyword in medium + + browser.get('https://medium.com/search?q=%s' % search_term) + browser.implicitly_wait(10) + + results = browser.find_elements_by_xpath('//a[contains(text(), "Read more")]') + + all_articles = [] + # get the links for all articles and store in list + for each_article in results: + all_articles.append(each_article.get_attribute('href')) + + # go to link of each article and export as PDF + for counter, url in enumerate(all_articles, 1): + print('Exporting article %s/%s: %s' % ((counter), search_count, url)) + + browser.get(url) + browser.implicitly_wait(10) + + # get title + article_title = browser.title + + # get url of page to export + url_to_export = browser.current_url + + # pdf name will contain article title + pdf = 'Medium-%s.pdf' % article_title + pdf = pdf.replace(' ', '-') + + # export pdf + quiet_mode = {'quiet': ''} + pdfkit.from_url(url_to_export, pdf, options=quiet_mode) + + # stop when we reach specified search count + if (counter == int(search_count)): + print('Complete. %s medium articles exported to PDF.' % search_count) + browser.close() + return + + +def process_option_1(): + + # get user settings + user_input = input('Enter search term followed by number of articles between 1 and 10 (e.g "learn python 5"): ') + user_input = user_input.split(' ') + + # last entry should be a number + try: + search_count = int(user_input[-1]) + except ValueError: + print('ERROR: Invalid input. The last entry must end with a number!') + return + + # remove number from list + user_input.pop() + + # join strings to load the phrase to search + search_term = ' ' + for each_word in user_input: + search_term = search_term + each_word + ' ' + + browser = setup_driver() + scrape_medium(browser, search_term, search_count) + exit() + + +def process_option_2(): + + # export a single article from the URL + url = input("Paste URL to convert to PDF (must begin with 'https://'): ") + + print('Converting to PDF...') + quiet_mode = {'quiet': ''} + pdfkit.from_url(url, 'converted.pdf', options=quiet_mode) + print('Complete. See "converted.pdf"') + exit() + + +def program_run(): + + while True: + # get user option + option = input("Enter '1' to search medium or '2' to export a single medium article: ") + + if option == '1': + process_option_1() + + elif option == '2': + process_option_2() + + elif option == 'x': + exit() + + else: + print("Invalid option. Try again! Or enter x to exit") + continue + pass + + +if __name__ == "__main__": + program_run() + pass diff --git a/articles_to_pdf/requirements.txt b/articles_to_pdf/requirements.txt index ef7b482e4..ea665f551 100644 --- a/articles_to_pdf/requirements.txt +++ b/articles_to_pdf/requirements.txt @@ -1,2 +1,2 @@ -pdfkit==0.6.1 -selenium==3.141.0 +pdfkit==0.6.1 +selenium==3.141.0 diff --git a/audio_book/PDF_TO_AUDIO.py b/audio_book/PDF_TO_AUDIO.py index d5a9e1fc8..309b3e66a 100644 --- a/audio_book/PDF_TO_AUDIO.py +++ b/audio_book/PDF_TO_AUDIO.py @@ -1,31 +1,31 @@ -import pyttsx3 -import PyPDF2 -from gtts import gTTS -from tkinter.filedialog import askopenfilename -from tkinter import Tk -Tk().withdraw() -filelocation = askopenfilename() # open the dialog GUI - - -book = open(filelocation, 'rb') - -pdfReader = PyPDF2.PdfFileReader(book) -pages = pdfReader.numPages -print("No. of pages: ", pages) -speaker = pyttsx3.init() -whole_text = '' -choice = input('choice? ') - -if choice == '1': - - for num in range(0, pages): - page = pdfReader.getPage(num) - text = page.extractText() - whole_text += text - speaker.say(text) - print("Reading: ", text) - speaker.runAndWait() - - -final_file = gTTS(text=whole_text, lang='en') # store file in variable -final_file.save("Output Audio.mp3") # Saving audio file +import pyttsx3 +import PyPDF2 +from gtts import gTTS +from tkinter.filedialog import askopenfilename +from tkinter import Tk +Tk().withdraw() +filelocation = askopenfilename() # open the dialog GUI + + +book = open(filelocation, 'rb') + +pdfReader = PyPDF2.PdfFileReader(book) +pages = pdfReader.numPages +print("No. of pages: ", pages) +speaker = pyttsx3.init() +whole_text = '' +choice = input('choice? ') + +if choice == '1': + + for num in range(0, pages): + page = pdfReader.getPage(num) + text = page.extractText() + whole_text += text + speaker.say(text) + print("Reading: ", text) + speaker.runAndWait() + + +final_file = gTTS(text=whole_text, lang='en') # store file in variable +final_file.save("Output Audio.mp3") # Saving audio file diff --git a/audio_book/README.md b/audio_book/README.md index 69758a4c6..f97bc9a9e 100644 --- a/audio_book/README.md +++ b/audio_book/README.md @@ -1,13 +1,13 @@ -# PDF TO AUDIO (AUDIOBOOK) - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## How to use : - Run the program and a dialog box will appear. Just select the .pdf file you want to convert to audio. - PRESS 1 if you want to hear the converted pdf at that moment (and saved afterwards). - Otherwise it will be saved automatically. The .mp3 file will be saved in the same directory. +# PDF TO AUDIO (AUDIOBOOK) + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## How to use : + Run the program and a dialog box will appear. Just select the .pdf file you want to convert to audio. + PRESS 1 if you want to hear the converted pdf at that moment (and saved afterwards). + Otherwise it will be saved automatically. The .mp3 file will be saved in the same directory. diff --git a/audio_book/makefile b/audio_book/makefile index e78e53c81..7aafa604a 100644 --- a/audio_book/makefile +++ b/audio_book/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/audio_book/requirements.txt b/audio_book/requirements.txt index 1523a0d51..36d3cfaa1 100644 --- a/audio_book/requirements.txt +++ b/audio_book/requirements.txt @@ -1,3 +1,3 @@ -gtts -PyPDF2 +gtts +PyPDF2 pyttsx3 \ No newline at end of file diff --git a/audio_recoder/README.md b/audio_recoder/README.md index 2ecd3413c..092c246c7 100644 --- a/audio_recoder/README.md +++ b/audio_recoder/README.md @@ -1,14 +1,14 @@ -#Audio Recorder - -##Library Required -- tkinter -- threading -- pyaudio -- wave - -##steps to record audio - -1. Run the .py file on your python IDE -2. Dialogue box with 2 options **Start** and **Stop** buttons. -3. Press **Start** to start the recording. -4. Press **Stop** to stop the recording. -5. After pressing stop, name the recorded .wap file with any name. +#Audio Recorder + +##Library Required +- tkinter +- threading +- pyaudio +- wave + +##steps to record audio - +1. Run the .py file on your python IDE +2. Dialogue box with 2 options **Start** and **Stop** buttons. +3. Press **Start** to start the recording. +4. Press **Stop** to stop the recording. +5. After pressing stop, name the recorded .wap file with any name. diff --git a/audio_recoder/audio_recorder.py b/audio_recoder/audio_recorder.py index 5f3f46bf0..fae1d81b6 100644 --- a/audio_recoder/audio_recorder.py +++ b/audio_recoder/audio_recorder.py @@ -1,59 +1,59 @@ -import tkinter as tk -import threading -import pyaudio -import wave - - -class App(): - chunk = 1024 - sample_format = pyaudio.paInt16 - channels = 2 - fs = 44100 - - frames = [] - - def __init__(self, master): - self.isrecording = False - self.button1 = tk.Button(main, text='Start', width=6, - command=self.startrecording) - self.button2 = tk.Button(main, text='Stop', width=6, - command=self.stoprecording) - self.button1.pack() - self.button2.pack() - - def startrecording(self): - self.p = pyaudio.PyAudio() - self.stream = self.p.open(format=self.sample_format, - channels=self.channels, rate=self.fs, - frames_per_buffer=self.chunk, input=True) - self.isrecording = True - self.button1['state'] = 'disable' - print('Recording') - t = threading.Thread(target=self.record) - t.start() - - def stoprecording(self): - self.isrecording = False - print('Recording Completed') - self.filename = input('Name the file?') - self.filename = self.filename + ".wav" - wf = wave.open(self.filename, 'wb') - wf.setnchannels(self.channels) - wf.setsampwidth(self.p.get_sample_size(self.sample_format)) - wf.setframerate(self.fs) - wf.writeframes(b''.join(self.frames)) - wf.close() - main.destroy() - - def record(self): - while self.isrecording: - data = self.stream.read(self.chunk) - self.frames.append(data) - - -main = tk.Tk() -main.title('Audio Recorder') -main.minsize(width=250, height=70) - -app = App(main) -main.mainloop() +import tkinter as tk +import threading +import pyaudio +import wave + + +class App(): + chunk = 1024 + sample_format = pyaudio.paInt16 + channels = 2 + fs = 44100 + + frames = [] + + def __init__(self, master): + self.isrecording = False + self.button1 = tk.Button(main, text='Start', width=6, + command=self.startrecording) + self.button2 = tk.Button(main, text='Stop', width=6, + command=self.stoprecording) + self.button1.pack() + self.button2.pack() + + def startrecording(self): + self.p = pyaudio.PyAudio() + self.stream = self.p.open(format=self.sample_format, + channels=self.channels, rate=self.fs, + frames_per_buffer=self.chunk, input=True) + self.isrecording = True + self.button1['state'] = 'disable' + print('Recording') + t = threading.Thread(target=self.record) + t.start() + + def stoprecording(self): + self.isrecording = False + print('Recording Completed') + self.filename = input('Name the file?') + self.filename = self.filename + ".wav" + wf = wave.open(self.filename, 'wb') + wf.setnchannels(self.channels) + wf.setsampwidth(self.p.get_sample_size(self.sample_format)) + wf.setframerate(self.fs) + wf.writeframes(b''.join(self.frames)) + wf.close() + main.destroy() + + def record(self): + while self.isrecording: + data = self.stream.read(self.chunk) + self.frames.append(data) + + +main = tk.Tk() +main.title('Audio Recorder') +main.minsize(width=250, height=70) + +app = App(main) +main.mainloop() diff --git a/audio_remover/README.md b/audio_remover/README.md index e5241d2b0..e5e4b1c2e 100644 --- a/audio_remover/README.md +++ b/audio_remover/README.md @@ -1,37 +1,37 @@ -# Audio Remover - -Remove the audio from video file - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -### Pre-requisites -Setup virtual environment from previous step or install requirements manually: -``` -$ pip install moviepy -``` - -### How to Use -``` -$ python audio-remover.py [-h] [-f F] [-n N] -``` - -If not adding any argument, the script will remove the audio from demo.mp4 and generate "demo_noAudio.mp4" as default - -``` -optional arguments: - -h, --help show this help message and exit - -f F The file path of target video. ex. /home/user/example.mp4. - Default value is "demo.mp4" - -n N The new file name. Default value is {current file - name}_noAudio.mp4 -``` - - - - - +# Audio Remover + +Remove the audio from video file + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +### Pre-requisites +Setup virtual environment from previous step or install requirements manually: +``` +$ pip install moviepy +``` + +### How to Use +``` +$ python audio-remover.py [-h] [-f F] [-n N] +``` + +If not adding any argument, the script will remove the audio from demo.mp4 and generate "demo_noAudio.mp4" as default + +``` +optional arguments: + -h, --help show this help message and exit + -f F The file path of target video. ex. /home/user/example.mp4. + Default value is "demo.mp4" + -n N The new file name. Default value is {current file + name}_noAudio.mp4 +``` + + + + + diff --git a/audio_remover/audio-remover.py b/audio_remover/audio-remover.py index 140fa63f9..9f03c1f6a 100644 --- a/audio_remover/audio-remover.py +++ b/audio_remover/audio-remover.py @@ -1,60 +1,60 @@ -from moviepy.editor import VideoFileClip -import os -import argparse - -# Define the base directory -base_dir = os.path.dirname(os.path.abspath(__file__)) - -# Define CLI arguments -parser = argparse.ArgumentParser() -parser.add_argument( - '-f', - type=str, - help='The file path of target video. ' - + 'ex. /home/user/example.mp4.\nDefault value is "demo.mp4"', - default=base_dir + '/demo.mp4' -) -parser.add_argument( - '-n', - type=str, - help='The new file name.\n' - + 'Default value is {current file name}_noAudio.mp4', -) - -args = parser.parse_args() -audio_path = args.f - -# Check whether or not the input video path is valid. If not, ask user to input again. -while True: - try: - VideoFileClip(audio_path) - break - except Exception: - print( - 'Directory or file is not valid,' - + ' please enter a valid file directory ...') - audio_path = str(input('Enter the video path again (absolute path without space): ')) - -origin_file = (lambda x: x.split('/')[-1])(audio_path) - -if args.n: - new_file = args.n -else: - new_file = f'{origin_file.split(".")[0]}_noAudio.{origin_file.split(".")[1]}' - - -def remove_audio(audio): - ''' - main function to remove audio from input video - ''' - video = VideoFileClip(audio) - video = video.without_audio() - video.write_videofile(os.path.join(base_dir, new_file)) - - -def main(): - remove_audio(audio_path) - - -if __name__ == '__main__': - main() +from moviepy.editor import VideoFileClip +import os +import argparse + +# Define the base directory +base_dir = os.path.dirname(os.path.abspath(__file__)) + +# Define CLI arguments +parser = argparse.ArgumentParser() +parser.add_argument( + '-f', + type=str, + help='The file path of target video. ' + + 'ex. /home/user/example.mp4.\nDefault value is "demo.mp4"', + default=base_dir + '/demo.mp4' +) +parser.add_argument( + '-n', + type=str, + help='The new file name.\n' + + 'Default value is {current file name}_noAudio.mp4', +) + +args = parser.parse_args() +audio_path = args.f + +# Check whether or not the input video path is valid. If not, ask user to input again. +while True: + try: + VideoFileClip(audio_path) + break + except Exception: + print( + 'Directory or file is not valid,' + + ' please enter a valid file directory ...') + audio_path = str(input('Enter the video path again (absolute path without space): ')) + +origin_file = (lambda x: x.split('/')[-1])(audio_path) + +if args.n: + new_file = args.n +else: + new_file = f'{origin_file.split(".")[0]}_noAudio.{origin_file.split(".")[1]}' + + +def remove_audio(audio): + ''' + main function to remove audio from input video + ''' + video = VideoFileClip(audio) + video = video.without_audio() + video.write_videofile(os.path.join(base_dir, new_file)) + + +def main(): + remove_audio(audio_path) + + +if __name__ == '__main__': + main() diff --git a/audio_remover/makefile b/audio_remover/makefile index dbcb008b6..00cc941a5 100644 --- a/audio_remover/makefile +++ b/audio_remover/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/audio_remover/requirements.txt b/audio_remover/requirements.txt index a384113ea..a21d91e87 100644 --- a/audio_remover/requirements.txt +++ b/audio_remover/requirements.txt @@ -1 +1 @@ -moviepy +moviepy diff --git a/auto_clicker/README.md b/auto_clicker/README.md index ab10cd799..a07e639f0 100644 --- a/auto_clicker/README.md +++ b/auto_clicker/README.md @@ -1,20 +1,20 @@ -# AutoClicker -This is a basic autoclicker, you can choose the delay you want between each click. -## Prerequisites - -**Python 3.8.x** - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -Then you can run the script! - -## Controls -Key | Action ---- | --- -F1 | Resume / Pause -ESC | Exit the program +# AutoClicker +This is a basic autoclicker, you can choose the delay you want between each click. +## Prerequisites + +**Python 3.8.x** + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +Then you can run the script! + +## Controls +Key | Action +--- | --- +F1 | Resume / Pause +ESC | Exit the program diff --git a/auto_clicker/autoclicker.py b/auto_clicker/autoclicker.py index f0091fe75..930c74ce3 100644 --- a/auto_clicker/autoclicker.py +++ b/auto_clicker/autoclicker.py @@ -1,57 +1,57 @@ -import pyautogui -from pynput.keyboard import Key, Listener - -# ======== Controls ======== -start_or_pause_key = Key.f1 -exit_key = Key.esc -delay = 1 # seconds - -# ==== global variables ==== -pause = True -running = True - - -def display_controls(): - - print("F1 = Start / Pause") - print("ESC = Exit\n") - - -def choose_delay(): - - try: - return float(input("Enter wanted delay (seconds): ")) - except ValueError: - print(f"You did not give a valid input, default delay : {delay}sec") - return delay - - -def key_press(key): - global running, pause - - if key == start_or_pause_key: - pause = not pause - print("< Pause >") if pause else print("< Start >") - elif key == exit_key: - running = False - print("< Exit >") - - -def main(): - - delay = choose_delay() - print(f"delay = {str(delay)}sec\n") - display_controls() - - listener = Listener(on_press=key_press) - listener.start() - - while running: - if not pause: - pyautogui.click(pyautogui.position()) - pyautogui.PAUSE = delay - listener.stop() - - -if __name__ == "__main__": - main() +import pyautogui +from pynput.keyboard import Key, Listener + +# ======== Controls ======== +start_or_pause_key = Key.f1 +exit_key = Key.esc +delay = 1 # seconds + +# ==== global variables ==== +pause = True +running = True + + +def display_controls(): + + print("F1 = Start / Pause") + print("ESC = Exit\n") + + +def choose_delay(): + + try: + return float(input("Enter wanted delay (seconds): ")) + except ValueError: + print(f"You did not give a valid input, default delay : {delay}sec") + return delay + + +def key_press(key): + global running, pause + + if key == start_or_pause_key: + pause = not pause + print("< Pause >") if pause else print("< Start >") + elif key == exit_key: + running = False + print("< Exit >") + + +def main(): + + delay = choose_delay() + print(f"delay = {str(delay)}sec\n") + display_controls() + + listener = Listener(on_press=key_press) + listener.start() + + while running: + if not pause: + pyautogui.click(pyautogui.position()) + pyautogui.PAUSE = delay + listener.stop() + + +if __name__ == "__main__": + main() diff --git a/auto_clicker/makefile b/auto_clicker/makefile index e78e53c81..7aafa604a 100644 --- a/auto_clicker/makefile +++ b/auto_clicker/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/auto_clicker/requirements.txt b/auto_clicker/requirements.txt index 68db6c87f..bdca035ba 100644 --- a/auto_clicker/requirements.txt +++ b/auto_clicker/requirements.txt @@ -1,2 +1,2 @@ -pyautogui +pyautogui pynput \ No newline at end of file diff --git a/auto_completer/README.md b/auto_completer/README.md index 87f60c415..e3411b1c2 100644 --- a/auto_completer/README.md +++ b/auto_completer/README.md @@ -1,32 +1,32 @@ -# Auto Complete / Language Modelling with N-Grams - -There are two main components here, -1. The Notebook -2. The Script - -It is recommended to go through the notebook to understand the basics of ngram model and how to implement it in PyTorch. - -Next we will use the trained model from the notebook to auto complete words of your own. (although it might not be perfect) - -> It is important to consider this just as a starting point. - -I will list out a few things you definitely need to make it run locally, - -1. Python 3.7 or later -2. PyTorch 1.6 or later -3. Numpy and Matplotlib -4. pkbar - keras style progress bar - -These are the major requirements. If you wish you can install my entire setup using this command - -`$ make install` - -> **Note: We will be using Charles Dickens' great novel "A Tale of two cities" to train our model.** - -You can download the novel using the code in cell 3 of the notebook, or from [this link](https://www.gutenberg.org/files/98/98-0.txt) - -If you decide to download from the website, make sure to remove unwanted text from gutenberg at the start and end of the txt file. However I have included the text file with all the changes in this repo. - -> **Author: [abhinand5](https://github.com/abhinand5)** - +# Auto Complete / Language Modelling with N-Grams + +There are two main components here, +1. The Notebook +2. The Script + +It is recommended to go through the notebook to understand the basics of ngram model and how to implement it in PyTorch. + +Next we will use the trained model from the notebook to auto complete words of your own. (although it might not be perfect) + +> It is important to consider this just as a starting point. + +I will list out a few things you definitely need to make it run locally, + +1. Python 3.7 or later +2. PyTorch 1.6 or later +3. Numpy and Matplotlib +4. pkbar - keras style progress bar + +These are the major requirements. If you wish you can install my entire setup using this command + +`$ make install` + +> **Note: We will be using Charles Dickens' great novel "A Tale of two cities" to train our model.** + +You can download the novel using the code in cell 3 of the notebook, or from [this link](https://www.gutenberg.org/files/98/98-0.txt) + +If you decide to download from the website, make sure to remove unwanted text from gutenberg at the start and end of the txt file. However I have included the text file with all the changes in this repo. + +> **Author: [abhinand5](https://github.com/abhinand5)** + Running the `auto-complete.py` script is very simple... just execute it and follow the prompts. \ No newline at end of file diff --git a/auto_completer/auto-complete.py b/auto_completer/auto-complete.py index 413fd04f0..dc70731de 100644 --- a/auto_completer/auto-complete.py +++ b/auto_completer/auto-complete.py @@ -1,145 +1,145 @@ -import torch -import torch.nn as nn -import torch.nn.functional as F - -import re - -device = torch.device("cpu") - - -class NGramModel(nn.Module): - """ - A simple Neural Network - for the sake of this tutorial - """ - - def __init__(self, vocab_size, embedding_dim, context_size): - super(NGramModel, self).__init__() - self.embedding = nn.Embedding(vocab_size, embedding_dim) - self.linear1 = nn.Linear(context_size * embedding_dim, 128) - self.linear2 = nn.Linear(128, vocab_size) - - def forward(self, inputs): - embeds = self.embedding(inputs).view((1, -1)) - x = F.relu(self.linear1(embeds)) - x = self.linear2(x) - log_probs = F.log_softmax(x, dim=1) - return log_probs - - -def make_inference(model, inputs, word_dict): - # Re-map dict - reverted_dict = dict(map(reversed, word_ixs.items())) - - model.eval() - with torch.no_grad(): - # Processing input - idxs = torch.tensor( - [word_dict[w] for w in inputs], dtype=torch.long, device=device - ) - - # Forward pass - log_probs = model(idxs) - - # Obtain probs - probs = torch.exp(log_probs) - - # obtain prediction - _, pred = torch.max(probs, 1) - - # Obtain predicted word index - pred_idx = pred.detach().cpu().numpy()[0] - - # Get predicted word from remapped dict - out = reverted_dict[pred_idx] - - return pred_idx, out - - -def generate_text_ngram(model, inputs, word_dict, n_words): - # Preprocess input - inputs = inputs.lower().split() - - # Get n, to slice out last n words from the predicted sentence - n = len(inputs) - - # Keep track of predicted words - pred_sent = inputs - # Collect pred indexes - pred_idxs = [] - - for w in range(n_words): - pred_idx, pred_w = make_inference(model, inputs, word_dict) - pred_sent.append(pred_w) - pred_idxs.append(pred_idx) - inputs = pred_sent[-n:] - - return pred_sent, pred_idxs - - -if __name__ == "__main__": - with open("tale_of_2_cities.txt", "r", encoding="utf-8") as f: - book = f.read() - - # Replace newline characters - book = re.sub("\n", " ", book) - book = re.sub("\ufeff", "", book) - - # Preprocess text - train_text = book.lower().split() - - # create vocabulary - vocabulary = set(train_text) - vocab_len = len(vocabulary) - - # Create word tokens - word_ixs = {word: i for i, word in enumerate(vocabulary)} - - # Making ngrams is also easy, you should be using (n-1) in slicing - def make_n_grams(text, n): - return [(text[i: i + n], text[i + n]) for i in range(len(text) - n)] - - # Define hyperparameters - N = 8 - EMBED_DIM = 32 - CONTEXT_LEN = N - - # create ngrams - n_grams = make_n_grams(train_text, N) - - model = NGramModel(vocab_len, EMBED_DIM, CONTEXT_LEN).to(device) - model.load_state_dict(torch.load("ngram_model_trained.ckpt")) - - d_sents = [ - "Yes, sir. We have oftentimes the honour to", - "You know that your parents had a great", - "London is a place where I'd love to", - "A large cask of wine has been dropped", - ] - - print("Choose from default sentences or enter you own!") - option = input("Enter 1 to choose from defaults: ") - - if option == "1": - print("Here are the default sentences...") - print("=====================================================") - print(f"Sentence 1 - {d_sents[0]}") - print(f"Sentence 2 - {d_sents[1]}") - print(f"Sentence 3 - {d_sents[2]}") - print(f"Sentence 4 - {d_sents[3]}") - print("=====================================================") - choice = int(input("Enter your choice (1-4): ")) - 1 - input_text = d_sents[choice] - else: - input_text = input("""Please enter an 8 word sentence - (Since loaded model uses 8-gram):""") - - n_seq = int(input("Enter number of more words to generate: ")) - - if len(input_text.split()) < 8: - raise("""Please enter an 8 word sentence - to start with or choose from defaults!!!""") - - out = " ".join(generate_text_ngram(model, input_text, word_ixs, n_seq)[0]) - - print(f"""\n\nThe Generated Text is: \n============================\n{out} - \n============================""") +import torch +import torch.nn as nn +import torch.nn.functional as F + +import re + +device = torch.device("cpu") + + +class NGramModel(nn.Module): + """ + A simple Neural Network - for the sake of this tutorial + """ + + def __init__(self, vocab_size, embedding_dim, context_size): + super(NGramModel, self).__init__() + self.embedding = nn.Embedding(vocab_size, embedding_dim) + self.linear1 = nn.Linear(context_size * embedding_dim, 128) + self.linear2 = nn.Linear(128, vocab_size) + + def forward(self, inputs): + embeds = self.embedding(inputs).view((1, -1)) + x = F.relu(self.linear1(embeds)) + x = self.linear2(x) + log_probs = F.log_softmax(x, dim=1) + return log_probs + + +def make_inference(model, inputs, word_dict): + # Re-map dict + reverted_dict = dict(map(reversed, word_ixs.items())) + + model.eval() + with torch.no_grad(): + # Processing input + idxs = torch.tensor( + [word_dict[w] for w in inputs], dtype=torch.long, device=device + ) + + # Forward pass + log_probs = model(idxs) + + # Obtain probs + probs = torch.exp(log_probs) + + # obtain prediction + _, pred = torch.max(probs, 1) + + # Obtain predicted word index + pred_idx = pred.detach().cpu().numpy()[0] + + # Get predicted word from remapped dict + out = reverted_dict[pred_idx] + + return pred_idx, out + + +def generate_text_ngram(model, inputs, word_dict, n_words): + # Preprocess input + inputs = inputs.lower().split() + + # Get n, to slice out last n words from the predicted sentence + n = len(inputs) + + # Keep track of predicted words + pred_sent = inputs + # Collect pred indexes + pred_idxs = [] + + for w in range(n_words): + pred_idx, pred_w = make_inference(model, inputs, word_dict) + pred_sent.append(pred_w) + pred_idxs.append(pred_idx) + inputs = pred_sent[-n:] + + return pred_sent, pred_idxs + + +if __name__ == "__main__": + with open("tale_of_2_cities.txt", "r", encoding="utf-8") as f: + book = f.read() + + # Replace newline characters + book = re.sub("\n", " ", book) + book = re.sub("\ufeff", "", book) + + # Preprocess text + train_text = book.lower().split() + + # create vocabulary + vocabulary = set(train_text) + vocab_len = len(vocabulary) + + # Create word tokens + word_ixs = {word: i for i, word in enumerate(vocabulary)} + + # Making ngrams is also easy, you should be using (n-1) in slicing + def make_n_grams(text, n): + return [(text[i: i + n], text[i + n]) for i in range(len(text) - n)] + + # Define hyperparameters + N = 8 + EMBED_DIM = 32 + CONTEXT_LEN = N + + # create ngrams + n_grams = make_n_grams(train_text, N) + + model = NGramModel(vocab_len, EMBED_DIM, CONTEXT_LEN).to(device) + model.load_state_dict(torch.load("ngram_model_trained.ckpt")) + + d_sents = [ + "Yes, sir. We have oftentimes the honour to", + "You know that your parents had a great", + "London is a place where I'd love to", + "A large cask of wine has been dropped", + ] + + print("Choose from default sentences or enter you own!") + option = input("Enter 1 to choose from defaults: ") + + if option == "1": + print("Here are the default sentences...") + print("=====================================================") + print(f"Sentence 1 - {d_sents[0]}") + print(f"Sentence 2 - {d_sents[1]}") + print(f"Sentence 3 - {d_sents[2]}") + print(f"Sentence 4 - {d_sents[3]}") + print("=====================================================") + choice = int(input("Enter your choice (1-4): ")) - 1 + input_text = d_sents[choice] + else: + input_text = input("""Please enter an 8 word sentence + (Since loaded model uses 8-gram):""") + + n_seq = int(input("Enter number of more words to generate: ")) + + if len(input_text.split()) < 8: + raise("""Please enter an 8 word sentence + to start with or choose from defaults!!!""") + + out = " ".join(generate_text_ngram(model, input_text, word_ixs, n_seq)[0]) + + print(f"""\n\nThe Generated Text is: \n============================\n{out} + \n============================""") diff --git a/auto_completer/makefile b/auto_completer/makefile index e78e53c81..7aafa604a 100644 --- a/auto_completer/makefile +++ b/auto_completer/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/auto_searcher/README.md b/auto_searcher/README.md index 70e1680d2..4a08e33db 100644 --- a/auto_searcher/README.md +++ b/auto_searcher/README.md @@ -1,13 +1,13 @@ -# AutoSeacrcher - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -**Just need to define image points and you will get same query searched** - -* Press F2 on any screen -* Press two mouse clicks over any text +# AutoSeacrcher + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +**Just need to define image points and you will get same query searched** + +* Press F2 on any screen +* Press two mouse clicks over any text diff --git a/auto_searcher/autosearcher.py b/auto_searcher/autosearcher.py index b0a593416..825e0f3a7 100644 --- a/auto_searcher/autosearcher.py +++ b/auto_searcher/autosearcher.py @@ -1,87 +1,87 @@ -from PIL import ImageGrab -import pytesseract -import threading -import pynput.mouse as ms -import pynput.keyboard as kb -from pynput.keyboard import Key, Controller -from selenium import webdriver - -keyboard = Controller() -pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' - - -class Autosearch(threading.Thread): - - def __init__(self, pImage, defined, pCords, clickCount, chromepath): - super(Autosearch, self).__init__() - - self.pImage = pImage - self.defined = defined - self.pCords = pCords - self.clickCount = clickCount - self.chromepath = chromepath - - def area_select(self): - - def on_click(x, y, button, pressed): - - if pressed: - - if self.clickCount == 0: - self.pCords[0], self.pCords[1] = x, y - - elif self.clickCount == 1: - self.pCords[2], self.pCords[3] = x, y - - self.defined = True - self.clickCount = 0 - return False - self.clickCount += 1 - - with ms.Listener(on_click=on_click) as listener: - listener.join() - - def keyPress(self): - - def on_press(key): - i = 10 - print(i) - - def on_release(key): - if key == Key.f2: - Autosearch.area_select(self) - Autosearch.capture(self) - return False - - with kb.Listener(on_press=on_press, on_release=on_release) as listener: - listener.join() - - def capture(self): - - if self.defined: - self.pImage = ImageGrab.grab(bbox=(self.pCords[0], self.pCords[1], self.pCords[2], self.pCords[3])) - parastring = pytesseract.image_to_string(self.pImage) - - parastring.replace('/n', '+') - parastring.replace(' ', '+') - - Autosearch.searches(self, parastring) - - else: - print('error') - - def searches(self, parastring): - - options = webdriver.ChromeOptions() - options.add_experimental_option('excludeSwitches', ['enable-automation']) - - browser = webdriver.Chrome(executable_path=self.chromepath, options=options) - url = browser.get("https://www.google.com/search?q=" + parastring + "&start=" + '0') - - browser.get(url) - - -if __name__ == '__main__': - - r = Autosearch(None, False, [0, 0, 0, 0], 0, "/Users/HP/Desktop/chromedriver") - r.keyPress() +from PIL import ImageGrab +import pytesseract +import threading +import pynput.mouse as ms +import pynput.keyboard as kb +from pynput.keyboard import Key, Controller +from selenium import webdriver + +keyboard = Controller() +pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' + + +class Autosearch(threading.Thread): + + def __init__(self, pImage, defined, pCords, clickCount, chromepath): + super(Autosearch, self).__init__() + + self.pImage = pImage + self.defined = defined + self.pCords = pCords + self.clickCount = clickCount + self.chromepath = chromepath + + def area_select(self): + + def on_click(x, y, button, pressed): + + if pressed: + + if self.clickCount == 0: + self.pCords[0], self.pCords[1] = x, y + + elif self.clickCount == 1: + self.pCords[2], self.pCords[3] = x, y + + self.defined = True + self.clickCount = 0 + return False + self.clickCount += 1 + + with ms.Listener(on_click=on_click) as listener: + listener.join() + + def keyPress(self): + + def on_press(key): + i = 10 + print(i) + + def on_release(key): + if key == Key.f2: + Autosearch.area_select(self) + Autosearch.capture(self) + return False + + with kb.Listener(on_press=on_press, on_release=on_release) as listener: + listener.join() + + def capture(self): + + if self.defined: + self.pImage = ImageGrab.grab(bbox=(self.pCords[0], self.pCords[1], self.pCords[2], self.pCords[3])) + parastring = pytesseract.image_to_string(self.pImage) + + parastring.replace('/n', '+') + parastring.replace(' ', '+') + + Autosearch.searches(self, parastring) + + else: + print('error') + + def searches(self, parastring): + + options = webdriver.ChromeOptions() + options.add_experimental_option('excludeSwitches', ['enable-automation']) + + browser = webdriver.Chrome(executable_path=self.chromepath, options=options) + url = browser.get("https://www.google.com/search?q=" + parastring + "&start=" + '0') + + browser.get(url) + + +if __name__ == '__main__': + + r = Autosearch(None, False, [0, 0, 0, 0], 0, "/Users/HP/Desktop/chromedriver") + r.keyPress() diff --git a/auto_searcher/makefile b/auto_searcher/makefile index e78e53c81..7aafa604a 100644 --- a/auto_searcher/makefile +++ b/auto_searcher/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/auto_searcher/requirements.txt b/auto_searcher/requirements.txt index 5e378bc69..bc417bcf2 100644 --- a/auto_searcher/requirements.txt +++ b/auto_searcher/requirements.txt @@ -1,4 +1,4 @@ -pynput==1.7.1 -pytesseract==0.3.6 -selenium==3.141.0 -Pillow==7.2.0 +pynput==1.7.1 +pytesseract==0.3.6 +selenium==3.141.0 +Pillow==7.2.0 diff --git a/auto_typer/README.md b/auto_typer/README.md index 40a90c37f..0d5d65d24 100644 --- a/auto_typer/README.md +++ b/auto_typer/README.md @@ -1,38 +1,38 @@ -# autotyper - -## Requirements - -First thing first, you must have [Tesseract](https://github.com/UB-Mannheim/tesseract/wiki) installed. - -### Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` -For windows user, -``` -py -m venv env -.\env\Scripts\Activate.ps1 -py -m pip install -r requirements.txt -``` - - -## How to use -Just stretch over image, it will type on prescribed point - -* Press Up key : For defining particular page -* Press Click : At (0,0) of your image for initialization -* Press Click : At (x,y) of your image for coordinates termination -* Press Down Key : For defining typing part - -## Examples -### First -
- -
- -## Second -
- +# autotyper + +## Requirements + +First thing first, you must have [Tesseract](https://github.com/UB-Mannheim/tesseract/wiki) installed. + +### Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` +For windows user, +``` +py -m venv env +.\env\Scripts\Activate.ps1 +py -m pip install -r requirements.txt +``` + + +## How to use +Just stretch over image, it will type on prescribed point + +* Press Up key : For defining particular page +* Press Click : At (0,0) of your image for initialization +* Press Click : At (x,y) of your image for coordinates termination +* Press Down Key : For defining typing part + +## Examples +### First +
+ +
+ +## Second +
+
\ No newline at end of file diff --git a/auto_typer/autotyper.py b/auto_typer/autotyper.py index a83453d3d..5fc6acd26 100644 --- a/auto_typer/autotyper.py +++ b/auto_typer/autotyper.py @@ -1,114 +1,114 @@ -from PIL import ImageGrab -from pytesseract import pytesseract -import time -import pynput.mouse as ms -import pynput.keyboard as kb -from pynput.keyboard import Key, Controller - -keyboard = Controller() - -pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' - - -class AutoTyper: - - clickCount = 0 - pCords = [0, 0, 0, 0] - defined = False - pImage = None - - def area_select(): - - print('Click twice to define TEXT window') - - def on_click(x, y, button, pressed): - - if pressed: - print('({0}, {1})'.format(x, y)) - if AutoTyper.clickCount == 0: - AutoTyper.pCords[0] = x - AutoTyper.pCords[1] = y - elif AutoTyper.clickCount == 1: - AutoTyper.pCords[2] = x - AutoTyper.pCords[3] = y - AutoTyper.defined = True - print('') - AutoTyper.clickCount = 0 - return False - AutoTyper.clickCount += 1 - - with ms.Listener(on_click=on_click) as listener: - listener.join() - - def keyPress(): - - print('UP ARROW') - - def on_press(key): - i = 10 - print(i) - - def on_release(key): - - if key == Key.up: - print('Pressed\n') - AutoTyper.area_select() - AutoTyper.capture() - - return False - - with kb.Listener(on_press=on_press, on_release=on_release) as listener: - listener.join() - - def startTyping(delaytime: float): - - print('DOWN ARROW') - - def on_press(key): - i = 10 - print(i) - - def on_release(key): - if key == Key.down: - print('Pressed\n') - AutoTyper.output(delaytime) - return False - - with kb.Listener(on_press=on_press, on_release=on_release) as listener: - listener.join() - - def capture(): - - if AutoTyper.defined: - AutoTyper.pImage = ImageGrab.grab(bbox=(AutoTyper.pCords[0], - AutoTyper.pCords[1], - AutoTyper.pCords[2], - AutoTyper.pCords[3])) - - else: - print('please define an area to OCR before trying to print') - - def output(delaytime: float): - - try: - paraString = pytesseract.image_to_string(AutoTyper.pImage) - except SystemError: - print('\n Error while processing your image, please retry.') - return False - - length = len(paraString) - - for i in range(length): - keyboard.press(paraString[i]) - keyboard.release(paraString[i]) - time.sleep(delaytime) - - -def start(delaytime: float): - - AutoTyper.keyPress() - AutoTyper.startTyping(delaytime) - - -if __name__ == '__main__': - start(0.01) +from PIL import ImageGrab +from pytesseract import pytesseract +import time +import pynput.mouse as ms +import pynput.keyboard as kb +from pynput.keyboard import Key, Controller + +keyboard = Controller() + +pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' + + +class AutoTyper: + + clickCount = 0 + pCords = [0, 0, 0, 0] + defined = False + pImage = None + + def area_select(): + + print('Click twice to define TEXT window') + + def on_click(x, y, button, pressed): + + if pressed: + print('({0}, {1})'.format(x, y)) + if AutoTyper.clickCount == 0: + AutoTyper.pCords[0] = x + AutoTyper.pCords[1] = y + elif AutoTyper.clickCount == 1: + AutoTyper.pCords[2] = x + AutoTyper.pCords[3] = y + AutoTyper.defined = True + print('') + AutoTyper.clickCount = 0 + return False + AutoTyper.clickCount += 1 + + with ms.Listener(on_click=on_click) as listener: + listener.join() + + def keyPress(): + + print('UP ARROW') + + def on_press(key): + i = 10 + print(i) + + def on_release(key): + + if key == Key.up: + print('Pressed\n') + AutoTyper.area_select() + AutoTyper.capture() + + return False + + with kb.Listener(on_press=on_press, on_release=on_release) as listener: + listener.join() + + def startTyping(delaytime: float): + + print('DOWN ARROW') + + def on_press(key): + i = 10 + print(i) + + def on_release(key): + if key == Key.down: + print('Pressed\n') + AutoTyper.output(delaytime) + return False + + with kb.Listener(on_press=on_press, on_release=on_release) as listener: + listener.join() + + def capture(): + + if AutoTyper.defined: + AutoTyper.pImage = ImageGrab.grab(bbox=(AutoTyper.pCords[0], + AutoTyper.pCords[1], + AutoTyper.pCords[2], + AutoTyper.pCords[3])) + + else: + print('please define an area to OCR before trying to print') + + def output(delaytime: float): + + try: + paraString = pytesseract.image_to_string(AutoTyper.pImage) + except SystemError: + print('\n Error while processing your image, please retry.') + return False + + length = len(paraString) + + for i in range(length): + keyboard.press(paraString[i]) + keyboard.release(paraString[i]) + time.sleep(delaytime) + + +def start(delaytime: float): + + AutoTyper.keyPress() + AutoTyper.startTyping(delaytime) + + +if __name__ == '__main__': + start(0.01) diff --git a/auto_typer/makefile b/auto_typer/makefile index e78e53c81..7aafa604a 100644 --- a/auto_typer/makefile +++ b/auto_typer/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/auto_typer/requirements.txt b/auto_typer/requirements.txt index 475b86a21..8144ae6a5 100644 --- a/auto_typer/requirements.txt +++ b/auto_typer/requirements.txt @@ -1,2 +1,2 @@ -pynput==1.7.1 -pytesseract==0.3.6 +pynput==1.7.1 +pytesseract==0.3.6 diff --git a/birthday_wisher/README.md b/birthday_wisher/README.md index 7dc6fc811..7ccf36eca 100644 --- a/birthday_wisher/README.md +++ b/birthday_wisher/README.md @@ -1,48 +1,48 @@ -# Bday Wish - -## Setup and activate virtual environment -For Unix based systems please execute the following command to create venv and install requirements. -``` -$ pip install -r requirements.txt -``` - -### Objectives -- [x] Telegram - birth_day_wish_telegram.py - Sends "Happy Birth Message to a Number" - - ##### Requirements - * Telegram API: Please refer to this [link](https://my.telegram.org/auth) - * Python - * A Smart Phone with telegram installed. - - ##### Usage: - `api_id`, `api_hash` and `token` should be applied within `birth_day_wish_telegram.py` - ``` - api_id = '' - api_hash = '' - token = '' - ``` - [ ] TODO: Improvement needed. - Desired date can be applide within `birth_day_wish_telegram.py`. - ``` - while True: - today = datetime.date.today() - if today != datetime.date(2020, 10, 15): - time.sleep(60 * 60 * 24) - else: - send_message("Happy Birth Day") - ``` - - simply execute the script: - ``` - python3 birth_day_wish_telegram.py - ``` - Please take `screen` and/or `tmux` into account. - -- [ ] Facebook - -- [ ] Twitter - -- [ ] Any further idea, Please open an [Issue](https://github.com/python-geeks/Automation-scripts/issues/new/choose) - - +# Bday Wish + +## Setup and activate virtual environment +For Unix based systems please execute the following command to create venv and install requirements. +``` +$ pip install -r requirements.txt +``` + +### Objectives +- [x] Telegram - birth_day_wish_telegram.py + Sends "Happy Birth Message to a Number" + + ##### Requirements + * Telegram API: Please refer to this [link](https://my.telegram.org/auth) + * Python + * A Smart Phone with telegram installed. + + ##### Usage: + `api_id`, `api_hash` and `token` should be applied within `birth_day_wish_telegram.py` + ``` + api_id = '' + api_hash = '' + token = '' + ``` + [ ] TODO: Improvement needed. + Desired date can be applide within `birth_day_wish_telegram.py`. + ``` + while True: + today = datetime.date.today() + if today != datetime.date(2020, 10, 15): + time.sleep(60 * 60 * 24) + else: + send_message("Happy Birth Day") + ``` + + simply execute the script: + ``` + python3 birth_day_wish_telegram.py + ``` + Please take `screen` and/or `tmux` into account. + +- [ ] Facebook + +- [ ] Twitter + +- [ ] Any further idea, Please open an [Issue](https://github.com/python-geeks/Automation-scripts/issues/new/choose) + + diff --git a/birthday_wisher/birth_day_wish_telegram.py b/birthday_wisher/birth_day_wish_telegram.py index 889f1d100..b1168ed3f 100644 --- a/birthday_wisher/birth_day_wish_telegram.py +++ b/birthday_wisher/birth_day_wish_telegram.py @@ -1,36 +1,36 @@ -#!/usr/bin/env python3 - -import datetime -import time - -from telethon.sync import TelegramClient -from telethon.tl.types import InputPeerUser - -api_id = '' -api_hash = '' -token = '' - -phone = '' - - -def send_message(msg): - client = TelegramClient('session', api_id, api_hash) - client.connect() - if not client.is_user_authorized(): - client.send_code_request(phone) - client.sign_in(phone, input('Enter the code: ')) - try: - receiver = InputPeerUser('user_id', 'user_hash') - client.send_message(receiver, msg, parse_mode='html') - except Exception as e: - print(e) - client.disconnect() - - -if __name__ == "__main__": - while True: - today = datetime.date.today() - if today != datetime.date(2020, 10, 15): - time.sleep(60 * 60 * 24) - else: - send_message("Happy Birth Day") +#!/usr/bin/env python3 + +import datetime +import time + +from telethon.sync import TelegramClient +from telethon.tl.types import InputPeerUser + +api_id = '' +api_hash = '' +token = '' + +phone = '' + + +def send_message(msg): + client = TelegramClient('session', api_id, api_hash) + client.connect() + if not client.is_user_authorized(): + client.send_code_request(phone) + client.sign_in(phone, input('Enter the code: ')) + try: + receiver = InputPeerUser('user_id', 'user_hash') + client.send_message(receiver, msg, parse_mode='html') + except Exception as e: + print(e) + client.disconnect() + + +if __name__ == "__main__": + while True: + today = datetime.date.today() + if today != datetime.date(2020, 10, 15): + time.sleep(60 * 60 * 24) + else: + send_message("Happy Birth Day") diff --git a/birthday_wisher/requirements.txt b/birthday_wisher/requirements.txt index fd0a7dc5b..e933062ca 100644 --- a/birthday_wisher/requirements.txt +++ b/birthday_wisher/requirements.txt @@ -1,2 +1,2 @@ -telebot==0.0.3 +telebot==0.0.3 Telethon==1.16.4 \ No newline at end of file diff --git a/book_manager/Dialog.py b/book_manager/Dialog.py index 2401e677b..387336fbc 100644 --- a/book_manager/Dialog.py +++ b/book_manager/Dialog.py @@ -1,141 +1,141 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '.\Dialog.ui' -# -# Created by: PyQt5 UI code generator 5.15.1 -# -# WARNING: Any manual changes made to this file will be lost when pyuic5 is -# run again. Do not edit this file unless you know what you are doing. - - -from PyQt5 import QtCore, QtGui, QtWidgets -import os - - -class Ui_Dialog(object): - def setupUi(self, Dialog, name='', path='', notes='', tags='', add=0): - Dialog.setObjectName("Dialog") - Dialog.resize(433, 310) - self.dialog = Dialog - self.add = add - self.data = {} - self.data['delete'] = False - self.data['name'] = '' - self.data['path'] = '' - self.data['tags'] = '' - self.data['notes'] = '' - self.label = QtWidgets.QLabel(Dialog) - self.label.setGeometry(QtCore.QRect(20, 30, 55, 16)) - self.label.setObjectName("label") - self.label_2 = QtWidgets.QLabel(Dialog) - self.label_2.setGeometry(QtCore.QRect(20, 60, 55, 16)) - self.label_2.setObjectName("label_2") - self.label_3 = QtWidgets.QLabel(Dialog) - self.label_3.setGeometry(QtCore.QRect(20, 90, 55, 16)) - self.label_3.setObjectName("label_3") - self.label_4 = QtWidgets.QLabel(Dialog) - self.label_4.setGeometry(QtCore.QRect(20, 130, 55, 16)) - self.label_4.setObjectName("label_4") - self.lineEdit = QtWidgets.QLineEdit(Dialog) - self.lineEdit.setGeometry(QtCore.QRect(100, 30, 261, 22)) - self.lineEdit.setObjectName("lineEdit") - self.lineEdit.setText(name) - self.lineEdit_2 = QtWidgets.QLabel(Dialog) - self.lineEdit_2.setGeometry(QtCore.QRect(100, 60, 261, 22)) - self.lineEdit_2.setObjectName("lineEdit_2") - self.lineEdit_2.setText(path) - self.lineEdit_3 = QtWidgets.QLineEdit(Dialog) - self.lineEdit_3.setGeometry(QtCore.QRect(100, 90, 261, 22)) - self.lineEdit_3.setObjectName("lineEdit_3") - self.lineEdit_3.setText(tags) - self.textEdit = QtWidgets.QTextEdit(Dialog) - self.textEdit.setGeometry(QtCore.QRect(100, 130, 261, 87)) - self.textEdit.setObjectName("textEdit") - self.textEdit.setText(notes) - if add == 0: - self.pushButton_delete = QtWidgets.QPushButton(Dialog) - self.pushButton_delete.setGeometry( - QtCore.QRect(20, 250, 93, 28)) - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap(".\\Icons/delete.webp"), - QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.pushButton_delete.setIcon(icon) - self.pushButton_delete.setObjectName("pushButton_delete") - self.pushButton_delete.clicked.connect(self.delete_clicked) - self.pushButton_ok = QtWidgets.QPushButton(Dialog) - self.pushButton_ok.setGeometry(QtCore.QRect(210, 250, 93, 28)) - self.pushButton_ok.setObjectName("pushButton_ok") - self.pushButton_ok.clicked.connect(self.ok_clicked) - self.pushButton_open = QtWidgets.QPushButton(Dialog) - self.pushButton_open.setGeometry(QtCore.QRect(370, 60, 31, 21)) - self.pushButton_open.clicked.connect(self.open_clicked) - self.pushButton_open.setText("") - icon1 = QtGui.QIcon() - icon1.addPixmap(QtGui.QPixmap(".\\Icons/open.webp"), - QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.pushButton_open.setIcon(icon1) - self.pushButton_open.setObjectName("pushButton_open") - self.pushButton_cancel = QtWidgets.QPushButton(Dialog) - self.pushButton_cancel.setGeometry(QtCore.QRect(320, 250, 93, 28)) - self.pushButton_cancel.setObjectName("pushButton_cancel") - self.pushButton_cancel.clicked.connect(self.cancel_clicked) - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Properties")) - self.label.setText(_translate("Dialog", "Name")) - self.label_2.setText(_translate("Dialog", "Path")) - self.label_3.setText(_translate("Dialog", "Tags")) - self.label_4.setText(_translate("Dialog", "Notes")) - if self.add == 0: - self.pushButton_delete.setText(_translate("Dialog", "Delete")) - self.pushButton_ok.setText(_translate("Dialog", "OK")) - self.pushButton_cancel.setText(_translate("Dialog", "Cancel")) - - def delete_clicked(self): - self.data['delete'] = True - self.dialog.accept() - - def cancel_clicked(self): - self.dialog.reject() - # pass - - def open_clicked(self): - try: - item = self.lineEdit_2.text().split('/') - finalpath = '/'.join(item[:-1]) - if finalpath: - os.startfile(finalpath) - except Exception as e: - print("Open Error Occurred", e) - - def ok_clicked(self): - self.data['name'] = self.lineEdit.text() - self.data['path'] = self.lineEdit_2.text() - self.data['tags'] = [i.strip() - for i in self.lineEdit_3.text().split(', ')] - self.data['notes'] = self.textEdit.toPlainText() - self.dialog.accept() - # pass - - # def checkval(self): - # self.data['name']=self.lineEdit.text() - # self.data['path'] = self.lineEdit_2.text() - # self.data['tags'] = self.lineEdit_3.text() - # self.data['notes'] = self.textEdit.toPlainText() - # self.dialog.accept() - # print(name) - # return name - # Dialog.done(name) - - -if __name__ == "__main__": - import sys - app = QtWidgets.QApplication(sys.argv) - Dialog = QtWidgets.QDialog() - ui = Ui_Dialog() - ui.setupUi(Dialog) - Dialog.show() - sys.exit(app.exec_()) +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '.\Dialog.ui' +# +# Created by: PyQt5 UI code generator 5.15.1 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets +import os + + +class Ui_Dialog(object): + def setupUi(self, Dialog, name='', path='', notes='', tags='', add=0): + Dialog.setObjectName("Dialog") + Dialog.resize(433, 310) + self.dialog = Dialog + self.add = add + self.data = {} + self.data['delete'] = False + self.data['name'] = '' + self.data['path'] = '' + self.data['tags'] = '' + self.data['notes'] = '' + self.label = QtWidgets.QLabel(Dialog) + self.label.setGeometry(QtCore.QRect(20, 30, 55, 16)) + self.label.setObjectName("label") + self.label_2 = QtWidgets.QLabel(Dialog) + self.label_2.setGeometry(QtCore.QRect(20, 60, 55, 16)) + self.label_2.setObjectName("label_2") + self.label_3 = QtWidgets.QLabel(Dialog) + self.label_3.setGeometry(QtCore.QRect(20, 90, 55, 16)) + self.label_3.setObjectName("label_3") + self.label_4 = QtWidgets.QLabel(Dialog) + self.label_4.setGeometry(QtCore.QRect(20, 130, 55, 16)) + self.label_4.setObjectName("label_4") + self.lineEdit = QtWidgets.QLineEdit(Dialog) + self.lineEdit.setGeometry(QtCore.QRect(100, 30, 261, 22)) + self.lineEdit.setObjectName("lineEdit") + self.lineEdit.setText(name) + self.lineEdit_2 = QtWidgets.QLabel(Dialog) + self.lineEdit_2.setGeometry(QtCore.QRect(100, 60, 261, 22)) + self.lineEdit_2.setObjectName("lineEdit_2") + self.lineEdit_2.setText(path) + self.lineEdit_3 = QtWidgets.QLineEdit(Dialog) + self.lineEdit_3.setGeometry(QtCore.QRect(100, 90, 261, 22)) + self.lineEdit_3.setObjectName("lineEdit_3") + self.lineEdit_3.setText(tags) + self.textEdit = QtWidgets.QTextEdit(Dialog) + self.textEdit.setGeometry(QtCore.QRect(100, 130, 261, 87)) + self.textEdit.setObjectName("textEdit") + self.textEdit.setText(notes) + if add == 0: + self.pushButton_delete = QtWidgets.QPushButton(Dialog) + self.pushButton_delete.setGeometry( + QtCore.QRect(20, 250, 93, 28)) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(".\\Icons/delete.webp"), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButton_delete.setIcon(icon) + self.pushButton_delete.setObjectName("pushButton_delete") + self.pushButton_delete.clicked.connect(self.delete_clicked) + self.pushButton_ok = QtWidgets.QPushButton(Dialog) + self.pushButton_ok.setGeometry(QtCore.QRect(210, 250, 93, 28)) + self.pushButton_ok.setObjectName("pushButton_ok") + self.pushButton_ok.clicked.connect(self.ok_clicked) + self.pushButton_open = QtWidgets.QPushButton(Dialog) + self.pushButton_open.setGeometry(QtCore.QRect(370, 60, 31, 21)) + self.pushButton_open.clicked.connect(self.open_clicked) + self.pushButton_open.setText("") + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(".\\Icons/open.webp"), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButton_open.setIcon(icon1) + self.pushButton_open.setObjectName("pushButton_open") + self.pushButton_cancel = QtWidgets.QPushButton(Dialog) + self.pushButton_cancel.setGeometry(QtCore.QRect(320, 250, 93, 28)) + self.pushButton_cancel.setObjectName("pushButton_cancel") + self.pushButton_cancel.clicked.connect(self.cancel_clicked) + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "Properties")) + self.label.setText(_translate("Dialog", "Name")) + self.label_2.setText(_translate("Dialog", "Path")) + self.label_3.setText(_translate("Dialog", "Tags")) + self.label_4.setText(_translate("Dialog", "Notes")) + if self.add == 0: + self.pushButton_delete.setText(_translate("Dialog", "Delete")) + self.pushButton_ok.setText(_translate("Dialog", "OK")) + self.pushButton_cancel.setText(_translate("Dialog", "Cancel")) + + def delete_clicked(self): + self.data['delete'] = True + self.dialog.accept() + + def cancel_clicked(self): + self.dialog.reject() + # pass + + def open_clicked(self): + try: + item = self.lineEdit_2.text().split('/') + finalpath = '/'.join(item[:-1]) + if finalpath: + os.startfile(finalpath) + except Exception as e: + print("Open Error Occurred", e) + + def ok_clicked(self): + self.data['name'] = self.lineEdit.text() + self.data['path'] = self.lineEdit_2.text() + self.data['tags'] = [i.strip() + for i in self.lineEdit_3.text().split(', ')] + self.data['notes'] = self.textEdit.toPlainText() + self.dialog.accept() + # pass + + # def checkval(self): + # self.data['name']=self.lineEdit.text() + # self.data['path'] = self.lineEdit_2.text() + # self.data['tags'] = self.lineEdit_3.text() + # self.data['notes'] = self.textEdit.toPlainText() + # self.dialog.accept() + # print(name) + # return name + # Dialog.done(name) + + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + Dialog = QtWidgets.QDialog() + ui = Ui_Dialog() + ui.setupUi(Dialog) + Dialog.show() + sys.exit(app.exec_()) diff --git a/book_manager/Dialog.ui b/book_manager/Dialog.ui index d5849f881..408cfeadc 100644 --- a/book_manager/Dialog.ui +++ b/book_manager/Dialog.ui @@ -1,171 +1,171 @@ - - - Dialog - - - - 0 - 0 - 433 - 310 - - - - Dialog - - - - - 20 - 30 - 55 - 16 - - - - Name - - - - - - 20 - 60 - 55 - 16 - - - - Path - - - - - - 20 - 90 - 55 - 16 - - - - Tags - - - - - - 20 - 130 - 55 - 16 - - - - Notes - - - - - - 100 - 30 - 261 - 22 - - - - - - - 100 - 60 - 261 - 22 - - - - - - - 100 - 90 - 261 - 22 - - - - - - - 100 - 130 - 261 - 87 - - - - - - - 20 - 250 - 93 - 28 - - - - Delete - - - - Icons/delete.webpIcons/delete.webp - - - - - - 210 - 250 - 93 - 28 - - - - OK - - - - - - 370 - 60 - 31 - 21 - - - - - - - - Icons/open.webpIcons/open.webp - - - - - - 320 - 250 - 93 - 28 - - - - Cancel - - - - - - + + + Dialog + + + + 0 + 0 + 433 + 310 + + + + Dialog + + + + + 20 + 30 + 55 + 16 + + + + Name + + + + + + 20 + 60 + 55 + 16 + + + + Path + + + + + + 20 + 90 + 55 + 16 + + + + Tags + + + + + + 20 + 130 + 55 + 16 + + + + Notes + + + + + + 100 + 30 + 261 + 22 + + + + + + + 100 + 60 + 261 + 22 + + + + + + + 100 + 90 + 261 + 22 + + + + + + + 100 + 130 + 261 + 87 + + + + + + + 20 + 250 + 93 + 28 + + + + Delete + + + + Icons/delete.webpIcons/delete.webp + + + + + + 210 + 250 + 93 + 28 + + + + OK + + + + + + 370 + 60 + 31 + 21 + + + + + + + + Icons/open.webpIcons/open.webp + + + + + + 320 + 250 + 93 + 28 + + + + Cancel + + + + + + diff --git a/book_manager/GUI.ui b/book_manager/GUI.ui index 7ac779847..d166e479a 100644 --- a/book_manager/GUI.ui +++ b/book_manager/GUI.ui @@ -1,246 +1,246 @@ - - - MainWindow - - - - 0 - 0 - 1037 - 622 - - - - MainWindow - - - - - - 170 - 20 - 831 - 601 - - - - - - - 10 - 10 - 131 - 61 - - - - - - - - - 85 - 170 - 0 - - - - - - - - - 85 - 170 - 0 - - - - - - - - - 85 - 170 - 0 - - - - - - - - - - - Icons/logo.png - - - true - - - - - - 20 - 80 - 111 - 41 - - - - Add Book - - - - Icons/add.svgIcons/add.svg - - - - - - 10 - 130 - 151 - 261 - - - - Search - - - - - 40 - 180 - 41 - 31 - - - - - - - - Icons/search.webpIcons/search.webp - - - - - - 10 - 40 - 95 - 20 - - - - Name - - - true - - - - - - 10 - 60 - 95 - 20 - - - - Link - - - - - - 10 - 80 - 95 - 20 - - - - Notes - - - - - - 10 - 100 - 95 - 20 - - - - Tags - - - - - - 10 - 20 - 61 - 16 - - - - Search by - - - - - - 10 - 130 - 55 - 16 - - - - KeyWord - - - - - - 10 - 150 - 113 - 22 - - - - - - - - - - 20 - 220 - 93 - 28 - - - - Clear Search - - - - groupBox - list_1 - label - button_add - - - - - - + + + MainWindow + + + + 0 + 0 + 1037 + 622 + + + + MainWindow + + + + + + 170 + 20 + 831 + 601 + + + + + + + 10 + 10 + 131 + 61 + + + + + + + + + 85 + 170 + 0 + + + + + + + + + 85 + 170 + 0 + + + + + + + + + 85 + 170 + 0 + + + + + + + + + + + Icons/logo.png + + + true + + + + + + 20 + 80 + 111 + 41 + + + + Add Book + + + + Icons/add.svgIcons/add.svg + + + + + + 10 + 130 + 151 + 261 + + + + Search + + + + + 40 + 180 + 41 + 31 + + + + + + + + Icons/search.webpIcons/search.webp + + + + + + 10 + 40 + 95 + 20 + + + + Name + + + true + + + + + + 10 + 60 + 95 + 20 + + + + Link + + + + + + 10 + 80 + 95 + 20 + + + + Notes + + + + + + 10 + 100 + 95 + 20 + + + + Tags + + + + + + 10 + 20 + 61 + 16 + + + + Search by + + + + + + 10 + 130 + 55 + 16 + + + + KeyWord + + + + + + 10 + 150 + 113 + 22 + + + + + + + + + + 20 + 220 + 93 + 28 + + + + Clear Search + + + + groupBox + list_1 + label + button_add + + + + + + diff --git a/book_manager/Icons/add.svg b/book_manager/Icons/add.svg index 5c6a931e5..5d43b921d 100644 --- a/book_manager/Icons/add.svg +++ b/book_manager/Icons/add.svg @@ -1,42 +1,42 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/book_manager/README.md b/book_manager/README.md index 2e6b376d1..fe7fb9f23 100644 --- a/book_manager/README.md +++ b/book_manager/README.md @@ -1,24 +1,24 @@ -# BookMan -![Icon](./Icons/logo.png) - -A minimalistic GUI application for managing books in local storage loaded with just enough features. -## Features -* Minimalistic UI Design for ease of use. -![Img](./Screenshots/UI.png) -* Add files from the file explorer in Windows. -![Img](./Screenshots/Add_File.png) -* Double click to access book properties and edit easily. -![Img](./Screenshots/Properties.png) -* Easily locate to the file location from within the application itself. -![Img](./Screenshots/Access.png) -* Use tags to organize your books as required and customization search options. -![Img](./Screenshots/Tags.png) - -## Instrutions -* Run the below instruction to use the application. - * pip install -r requirements.txt -* To run the application, - * python bookman.py - -# Creator -Code written by [Kiran MHM](https://github.com/GoluffyxD) +# BookMan +![Icon](./Icons/logo.png) + +A minimalistic GUI application for managing books in local storage loaded with just enough features. +## Features +* Minimalistic UI Design for ease of use. +![Img](./Screenshots/UI.png) +* Add files from the file explorer in Windows. +![Img](./Screenshots/Add_File.png) +* Double click to access book properties and edit easily. +![Img](./Screenshots/Properties.png) +* Easily locate to the file location from within the application itself. +![Img](./Screenshots/Access.png) +* Use tags to organize your books as required and customization search options. +![Img](./Screenshots/Tags.png) + +## Instrutions +* Run the below instruction to use the application. + * pip install -r requirements.txt +* To run the application, + * python bookman.py + +# Creator +Code written by [Kiran MHM](https://github.com/GoluffyxD) diff --git a/book_manager/book.py b/book_manager/book.py index c151998b9..e5add831f 100644 --- a/book_manager/book.py +++ b/book_manager/book.py @@ -1,69 +1,69 @@ - -# conn = sqlite3.connect("books.db") - -# c = conn.cursor() - -# c.execute(""" CREATE TABLE books ( -# name text, -# path text primary key, -# tags text, -# notes text -# ) """) - -# c.execute("INSERT INTO books VALUES ('test1', 'path1', 'notes1', 'fiction')") -# conn.commit() - - -def add_book(conn, book): - c = conn.cursor() - c.execute("INSERT INTO books VALUES (?, ?, ?, ?)", - (book.name, book.path, book.notes, book.tags)) - conn.commit() - - -def delete_book(conn, path): - c = conn.cursor() - c.execute("DELETE FROM books WHERE path = ? ", (path, )) - conn.commit() - - -def edit_book(conn, prop, value, name): - c = conn.cursor() - if prop in ['name', 'notes', 'tags', 'path']: - c.execute(f"UPDATE books SET {prop} = ? WHERE path = ?", (value, name)) - conn.commit() - - -def show_books(conn): - c = conn.cursor() - c.execute("SELECT * from books") - finresults = [] - results = c.fetchall() - for i in results: - finresults.append([i[0], i[1], i[2].split(', '), i[3]]) - return finresults - - -def search_book(conn, prop, value): - c = conn.cursor() - if prop in ['name', 'notes', 'tags', 'path']: - c.execute(f"SELECT * FROM books where {prop} = ?", (value, )) - conn.commit() - -# print("Welcome to BookMan") -# while True: -# print("1.Add New Book\n2.Edit a Book\n3.Display all books\n4.Delete a book\n5.Exit") -# n=int(input()) -# if n==1: -# name, path, notes, tags= input("Enter Book Details: ").split() -# add_book(Book(name, path, notes, tags)) -# elif n==2: -# prop, value, name = input("Enter property, new value and book name: ").split() -# edit_book(prop, value, name) -# elif n==3: -# show_books() -# elif n==4: -# name = input("Enter book to delete") -# delete_book(name) -# else: -# break + +# conn = sqlite3.connect("books.db") + +# c = conn.cursor() + +# c.execute(""" CREATE TABLE books ( +# name text, +# path text primary key, +# tags text, +# notes text +# ) """) + +# c.execute("INSERT INTO books VALUES ('test1', 'path1', 'notes1', 'fiction')") +# conn.commit() + + +def add_book(conn, book): + c = conn.cursor() + c.execute("INSERT INTO books VALUES (?, ?, ?, ?)", + (book.name, book.path, book.notes, book.tags)) + conn.commit() + + +def delete_book(conn, path): + c = conn.cursor() + c.execute("DELETE FROM books WHERE path = ? ", (path, )) + conn.commit() + + +def edit_book(conn, prop, value, name): + c = conn.cursor() + if prop in ['name', 'notes', 'tags', 'path']: + c.execute(f"UPDATE books SET {prop} = ? WHERE path = ?", (value, name)) + conn.commit() + + +def show_books(conn): + c = conn.cursor() + c.execute("SELECT * from books") + finresults = [] + results = c.fetchall() + for i in results: + finresults.append([i[0], i[1], i[2].split(', '), i[3]]) + return finresults + + +def search_book(conn, prop, value): + c = conn.cursor() + if prop in ['name', 'notes', 'tags', 'path']: + c.execute(f"SELECT * FROM books where {prop} = ?", (value, )) + conn.commit() + +# print("Welcome to BookMan") +# while True: +# print("1.Add New Book\n2.Edit a Book\n3.Display all books\n4.Delete a book\n5.Exit") +# n=int(input()) +# if n==1: +# name, path, notes, tags= input("Enter Book Details: ").split() +# add_book(Book(name, path, notes, tags)) +# elif n==2: +# prop, value, name = input("Enter property, new value and book name: ").split() +# edit_book(prop, value, name) +# elif n==3: +# show_books() +# elif n==4: +# name = input("Enter book to delete") +# delete_book(name) +# else: +# break diff --git a/book_manager/bookman.py b/book_manager/bookman.py index aa41d6869..c7975ddd8 100644 --- a/book_manager/bookman.py +++ b/book_manager/bookman.py @@ -1,245 +1,245 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'GUI.ui' -# -# Created by: PyQt5 UI code generator 5.15.1 -# -# WARNING: Any manual changes made to this file will be lost when pyuic5 is -# run again. Do not edit this file unless you know what you are doing. - - -from PyQt5 import QtCore, QtGui, QtWidgets -import sqlite3 -from book import show_books, add_book, edit_book, delete_book -from Dialog import Ui_Dialog -from data_model import Book -conn = sqlite3.connect("books.db") - -books = [] - - -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - global books - MainWindow.setObjectName("MainWindow") - MainWindow.resize(1037, 622) - self.centralwidget = QtWidgets.QWidget(MainWindow) - self.centralwidget.setObjectName("centralwidget") - self.list_1 = QtWidgets.QListWidget(self.centralwidget) - self.list_1.setGeometry(QtCore.QRect(170, 20, 831, 601)) - self.list_1.setObjectName("list_1") - books = show_books(conn) - for item in books: - newitem = QtWidgets.QListWidgetItem( - f"Name: {item[0]}\nPath: {item[1]}\nTags: {', '.join(item[2])}\nNotes: {item[3]}\n") - font = QtGui.QFont('Times', 12) - font.setBold(True) - font.setWeight(50) - newitem.setFont(font) - self.list_1.addItem(newitem) - self.list_1.itemDoubleClicked.connect(self.open_properties) - # self.list_1.item - self.label = QtWidgets.QLabel(self.centralwidget) - self.label.setGeometry(QtCore.QRect(10, 10, 131, 61)) - palette = QtGui.QPalette() - brush = QtGui.QBrush(QtGui.QColor(85, 170, 0)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Active, - QtGui.QPalette.BrightText, brush) - brush = QtGui.QBrush(QtGui.QColor(85, 170, 0)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Inactive, - QtGui.QPalette.BrightText, brush) - brush = QtGui.QBrush(QtGui.QColor(85, 170, 0)) - brush.setStyle(QtCore.Qt.SolidPattern) - palette.setBrush(QtGui.QPalette.Disabled, - QtGui.QPalette.BrightText, brush) - self.label.setPalette(palette) - self.label.setText("") - self.label.setPixmap(QtGui.QPixmap("Icons/logo.png")) - self.label.setScaledContents(True) - self.label.setObjectName("label") - self.button_add = QtWidgets.QPushButton(self.centralwidget) - self.button_add.setGeometry(QtCore.QRect(20, 80, 111, 41)) - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap("Icons/add.svg"), - QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.button_add.setIcon(icon) - self.button_add.setObjectName("button_add") - self.button_add.clicked.connect(self.add_books) - self.groupBox = QtWidgets.QGroupBox(self.centralwidget) - self.groupBox.setGeometry(QtCore.QRect(10, 130, 151, 261)) - self.groupBox.setObjectName("groupBox") - self.button_search = QtWidgets.QPushButton(self.groupBox) - self.button_search.setGeometry(QtCore.QRect(40, 180, 41, 31)) - self.button_search.setText("") - icon1 = QtGui.QIcon() - icon1.addPixmap(QtGui.QPixmap("Icons/search.webp"), - QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.button_search.setIcon(icon1) - self.button_search.setObjectName("button_search") - self.button_search.clicked.connect(self.search_books) - self.radioButton_1 = QtWidgets.QRadioButton(self.groupBox) - self.radioButton_1.setGeometry(QtCore.QRect(10, 40, 95, 20)) - self.radioButton_1.setChecked(True) - self.radioButton_1.setObjectName("radioButton_1") - self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox) - self.radioButton_2.setGeometry(QtCore.QRect(10, 60, 95, 20)) - self.radioButton_2.setObjectName("radioButton_2") - self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox) - self.radioButton_3.setGeometry(QtCore.QRect(10, 80, 95, 20)) - self.radioButton_3.setObjectName("radioButton_3") - self.radioButton_4 = QtWidgets.QRadioButton(self.groupBox) - self.radioButton_4.setGeometry(QtCore.QRect(10, 100, 95, 20)) - self.radioButton_4.setObjectName("radioButton_4") - self.label_2 = QtWidgets.QLabel(self.groupBox) - self.label_2.setGeometry(QtCore.QRect(10, 20, 61, 16)) - self.label_2.setObjectName("label_2") - self.label_3 = QtWidgets.QLabel(self.groupBox) - self.label_3.setGeometry(QtCore.QRect(10, 130, 55, 16)) - self.label_3.setObjectName("label_3") - self.lineEdit = QtWidgets.QLineEdit(self.groupBox) - self.lineEdit.setGeometry(QtCore.QRect(10, 150, 113, 22)) - self.lineEdit.setText("") - self.lineEdit.setObjectName("lineEdit") - self.pushButton = QtWidgets.QPushButton(self.groupBox) - self.pushButton.setGeometry(QtCore.QRect(20, 220, 93, 28)) - self.pushButton.setObjectName("pushButton") - self.pushButton.clicked.connect(self.show_all) - self.groupBox.raise_() - self.list_1.raise_() - self.label.raise_() - self.button_add.raise_() - MainWindow.setCentralWidget(self.centralwidget) - self.statusbar = QtWidgets.QStatusBar(MainWindow) - self.statusbar.setObjectName("statusbar") - MainWindow.setStatusBar(self.statusbar) - - self.retranslateUi(MainWindow) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "BookMan")) - self.button_add.setText(_translate("MainWindow", " Add Book")) - self.groupBox.setTitle(_translate("MainWindow", "Search")) - self.radioButton_1.setText(_translate("MainWindow", "Name")) - self.radioButton_2.setText(_translate("MainWindow", "Link")) - self.radioButton_3.setText(_translate("MainWindow", "Tags")) - self.radioButton_4.setText(_translate("MainWindow", "Notes")) - self.label_2.setText(_translate("MainWindow", "Search by")) - self.label_3.setText(_translate("MainWindow", "KeyWord")) - self.pushButton.setText(_translate("MainWindow", "Clear Search")) - - def show_all(self): - self.list_1.clear() - global books - # print(books) - for item in books: - newitem = QtWidgets.QListWidgetItem( - f"Name: {item[0]}\nPath: {item[1]}\nTags: {', '.join(item[2])}\nNotes: {item[3]}\n") - font = QtGui.QFont('Times', 12) - font.setBold(True) - font.setWeight(50) - newitem.setFont(font) - self.list_1.addItem(newitem) - # print("Clicked") - self.lineEdit.clear() - - def search_books(self): - global books - results = [] - searchtext = self.lineEdit.text() - field = [self.radioButton_1.isChecked(), self.radioButton_2.isChecked( - ), self.radioButton_3.isChecked(), self.radioButton_4.isChecked()] - ind = field.index(True) - for i in books: - if searchtext in i[ind]: - results.append(i) - self.list_1.clear() - for item in results: - newitem = QtWidgets.QListWidgetItem( - f"Name: {item[0]}\nPath: {item[1]}\nTags: {', '.join(item[2])}\nNotes: {item[3]}\n") - font = QtGui.QFont('Times', 12) - font.setBold(True) - font.setWeight(50) - newitem.setFont(font) - self.list_1.addItem(newitem) - - def add_books(self): - global books - res = self.open_dialog_box() - name = res[0].split('/')[-1] - Dialog2 = QtWidgets.QDialog() - ui = Ui_Dialog() - ui.setupUi(Dialog2, path=res[0], name=name, add=1) - Dialog2.show() - s = Dialog2.exec_() - if s == 1: - if ui.data['path'] not in [i[1] for i in books]: - books.append([ui.data['name'], ui.data['path'], - ui.data['tags'], ui.data['notes']]) - item = books[-1] - newitem = QtWidgets.QListWidgetItem( - f"Name: {item[0]}\nPath: {item[1]}\nTags: {', '.join(item[2])}\nNotes: {item[3]}\n") - font = QtGui.QFont('Times', 12) - font.setBold(True) - font.setWeight(50) - newitem.setFont(font) - self.list_1.addItem(newitem) - add_book(conn, Book(ui.data['name'], ui.data['path'], ', '.join( - item[2]), ui.data['notes'])) - - def open_dialog_box(self): - filename = QtWidgets.QFileDialog.getOpenFileName() - return filename - # print(filename) - - def open_properties(self, item): - global books - lines = item.text().split('\n') - final = [] - for index, i in enumerate(lines): - lines[index] = i.strip() - val = ' '.join(lines[index].split(' ')[1:]) - final.append(val) - Dialog2 = QtWidgets.QDialog() - ui = Ui_Dialog() - ui.setupUi( - Dialog2, path=final[1], name=final[0], tags=final[2], notes=final[3]) - Dialog2.show() - s = Dialog2.exec_() - if s == 1: - if ui.data['delete'] is True: - for index, i in enumerate(books): - if i[1] == final[1]: - ind = index - break - delete_book(conn, books[ind][1]) - del books[ind] - self.show_all() - else: - # Ok is clicked - for index, i in enumerate(books): - if i[1] == final[1]: - ind = index - break - books[index][0] = ui.data['name'] - books[index][1] = ui.data['path'] - books[index][2] = ui.data['tags'] - books[index][3] = ui.data['notes'] - edit_book(conn, 'name', books[index][0], books[index][1]) - edit_book(conn, 'tags', ', '.join( - books[index][2]), books[index][1]) - edit_book(conn, 'notes', books[index][3], books[index][1]) - self.show_all() - - -if __name__ == "__main__": - import sys - app = QtWidgets.QApplication(sys.argv) - MainWindow = QtWidgets.QMainWindow() - ui = Ui_MainWindow() - ui.setupUi(MainWindow) - MainWindow.show() - sys.exit(app.exec_()) +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'GUI.ui' +# +# Created by: PyQt5 UI code generator 5.15.1 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets +import sqlite3 +from book import show_books, add_book, edit_book, delete_book +from Dialog import Ui_Dialog +from data_model import Book +conn = sqlite3.connect("books.db") + +books = [] + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + global books + MainWindow.setObjectName("MainWindow") + MainWindow.resize(1037, 622) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.list_1 = QtWidgets.QListWidget(self.centralwidget) + self.list_1.setGeometry(QtCore.QRect(170, 20, 831, 601)) + self.list_1.setObjectName("list_1") + books = show_books(conn) + for item in books: + newitem = QtWidgets.QListWidgetItem( + f"Name: {item[0]}\nPath: {item[1]}\nTags: {', '.join(item[2])}\nNotes: {item[3]}\n") + font = QtGui.QFont('Times', 12) + font.setBold(True) + font.setWeight(50) + newitem.setFont(font) + self.list_1.addItem(newitem) + self.list_1.itemDoubleClicked.connect(self.open_properties) + # self.list_1.item + self.label = QtWidgets.QLabel(self.centralwidget) + self.label.setGeometry(QtCore.QRect(10, 10, 131, 61)) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(85, 170, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, + QtGui.QPalette.BrightText, brush) + brush = QtGui.QBrush(QtGui.QColor(85, 170, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, + QtGui.QPalette.BrightText, brush) + brush = QtGui.QBrush(QtGui.QColor(85, 170, 0)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, + QtGui.QPalette.BrightText, brush) + self.label.setPalette(palette) + self.label.setText("") + self.label.setPixmap(QtGui.QPixmap("Icons/logo.png")) + self.label.setScaledContents(True) + self.label.setObjectName("label") + self.button_add = QtWidgets.QPushButton(self.centralwidget) + self.button_add.setGeometry(QtCore.QRect(20, 80, 111, 41)) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap("Icons/add.svg"), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.button_add.setIcon(icon) + self.button_add.setObjectName("button_add") + self.button_add.clicked.connect(self.add_books) + self.groupBox = QtWidgets.QGroupBox(self.centralwidget) + self.groupBox.setGeometry(QtCore.QRect(10, 130, 151, 261)) + self.groupBox.setObjectName("groupBox") + self.button_search = QtWidgets.QPushButton(self.groupBox) + self.button_search.setGeometry(QtCore.QRect(40, 180, 41, 31)) + self.button_search.setText("") + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap("Icons/search.webp"), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.button_search.setIcon(icon1) + self.button_search.setObjectName("button_search") + self.button_search.clicked.connect(self.search_books) + self.radioButton_1 = QtWidgets.QRadioButton(self.groupBox) + self.radioButton_1.setGeometry(QtCore.QRect(10, 40, 95, 20)) + self.radioButton_1.setChecked(True) + self.radioButton_1.setObjectName("radioButton_1") + self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox) + self.radioButton_2.setGeometry(QtCore.QRect(10, 60, 95, 20)) + self.radioButton_2.setObjectName("radioButton_2") + self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox) + self.radioButton_3.setGeometry(QtCore.QRect(10, 80, 95, 20)) + self.radioButton_3.setObjectName("radioButton_3") + self.radioButton_4 = QtWidgets.QRadioButton(self.groupBox) + self.radioButton_4.setGeometry(QtCore.QRect(10, 100, 95, 20)) + self.radioButton_4.setObjectName("radioButton_4") + self.label_2 = QtWidgets.QLabel(self.groupBox) + self.label_2.setGeometry(QtCore.QRect(10, 20, 61, 16)) + self.label_2.setObjectName("label_2") + self.label_3 = QtWidgets.QLabel(self.groupBox) + self.label_3.setGeometry(QtCore.QRect(10, 130, 55, 16)) + self.label_3.setObjectName("label_3") + self.lineEdit = QtWidgets.QLineEdit(self.groupBox) + self.lineEdit.setGeometry(QtCore.QRect(10, 150, 113, 22)) + self.lineEdit.setText("") + self.lineEdit.setObjectName("lineEdit") + self.pushButton = QtWidgets.QPushButton(self.groupBox) + self.pushButton.setGeometry(QtCore.QRect(20, 220, 93, 28)) + self.pushButton.setObjectName("pushButton") + self.pushButton.clicked.connect(self.show_all) + self.groupBox.raise_() + self.list_1.raise_() + self.label.raise_() + self.button_add.raise_() + MainWindow.setCentralWidget(self.centralwidget) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "BookMan")) + self.button_add.setText(_translate("MainWindow", " Add Book")) + self.groupBox.setTitle(_translate("MainWindow", "Search")) + self.radioButton_1.setText(_translate("MainWindow", "Name")) + self.radioButton_2.setText(_translate("MainWindow", "Link")) + self.radioButton_3.setText(_translate("MainWindow", "Tags")) + self.radioButton_4.setText(_translate("MainWindow", "Notes")) + self.label_2.setText(_translate("MainWindow", "Search by")) + self.label_3.setText(_translate("MainWindow", "KeyWord")) + self.pushButton.setText(_translate("MainWindow", "Clear Search")) + + def show_all(self): + self.list_1.clear() + global books + # print(books) + for item in books: + newitem = QtWidgets.QListWidgetItem( + f"Name: {item[0]}\nPath: {item[1]}\nTags: {', '.join(item[2])}\nNotes: {item[3]}\n") + font = QtGui.QFont('Times', 12) + font.setBold(True) + font.setWeight(50) + newitem.setFont(font) + self.list_1.addItem(newitem) + # print("Clicked") + self.lineEdit.clear() + + def search_books(self): + global books + results = [] + searchtext = self.lineEdit.text() + field = [self.radioButton_1.isChecked(), self.radioButton_2.isChecked( + ), self.radioButton_3.isChecked(), self.radioButton_4.isChecked()] + ind = field.index(True) + for i in books: + if searchtext in i[ind]: + results.append(i) + self.list_1.clear() + for item in results: + newitem = QtWidgets.QListWidgetItem( + f"Name: {item[0]}\nPath: {item[1]}\nTags: {', '.join(item[2])}\nNotes: {item[3]}\n") + font = QtGui.QFont('Times', 12) + font.setBold(True) + font.setWeight(50) + newitem.setFont(font) + self.list_1.addItem(newitem) + + def add_books(self): + global books + res = self.open_dialog_box() + name = res[0].split('/')[-1] + Dialog2 = QtWidgets.QDialog() + ui = Ui_Dialog() + ui.setupUi(Dialog2, path=res[0], name=name, add=1) + Dialog2.show() + s = Dialog2.exec_() + if s == 1: + if ui.data['path'] not in [i[1] for i in books]: + books.append([ui.data['name'], ui.data['path'], + ui.data['tags'], ui.data['notes']]) + item = books[-1] + newitem = QtWidgets.QListWidgetItem( + f"Name: {item[0]}\nPath: {item[1]}\nTags: {', '.join(item[2])}\nNotes: {item[3]}\n") + font = QtGui.QFont('Times', 12) + font.setBold(True) + font.setWeight(50) + newitem.setFont(font) + self.list_1.addItem(newitem) + add_book(conn, Book(ui.data['name'], ui.data['path'], ', '.join( + item[2]), ui.data['notes'])) + + def open_dialog_box(self): + filename = QtWidgets.QFileDialog.getOpenFileName() + return filename + # print(filename) + + def open_properties(self, item): + global books + lines = item.text().split('\n') + final = [] + for index, i in enumerate(lines): + lines[index] = i.strip() + val = ' '.join(lines[index].split(' ')[1:]) + final.append(val) + Dialog2 = QtWidgets.QDialog() + ui = Ui_Dialog() + ui.setupUi( + Dialog2, path=final[1], name=final[0], tags=final[2], notes=final[3]) + Dialog2.show() + s = Dialog2.exec_() + if s == 1: + if ui.data['delete'] is True: + for index, i in enumerate(books): + if i[1] == final[1]: + ind = index + break + delete_book(conn, books[ind][1]) + del books[ind] + self.show_all() + else: + # Ok is clicked + for index, i in enumerate(books): + if i[1] == final[1]: + ind = index + break + books[index][0] = ui.data['name'] + books[index][1] = ui.data['path'] + books[index][2] = ui.data['tags'] + books[index][3] = ui.data['notes'] + edit_book(conn, 'name', books[index][0], books[index][1]) + edit_book(conn, 'tags', ', '.join( + books[index][2]), books[index][1]) + edit_book(conn, 'notes', books[index][3], books[index][1]) + self.show_all() + + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + MainWindow = QtWidgets.QMainWindow() + ui = Ui_MainWindow() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) diff --git a/book_manager/data_model.py b/book_manager/data_model.py index 9dbeaee32..c52d0e140 100644 --- a/book_manager/data_model.py +++ b/book_manager/data_model.py @@ -1,11 +1,11 @@ -class Book: - """ The Class for Book Record Details """ - - def __init__(self, name, path, tags, notes): - self.name = name - self.path = path - self.notes = notes - self.tags = tags - - def __repr__(self): - return f"Book Name: {self.name}\n Book path: {self.path} \n Book Notes: {self.notes}\n Book Tags: {self.tags}" +class Book: + """ The Class for Book Record Details """ + + def __init__(self, name, path, tags, notes): + self.name = name + self.path = path + self.notes = notes + self.tags = tags + + def __repr__(self): + return f"Book Name: {self.name}\n Book path: {self.path} \n Book Notes: {self.notes}\n Book Tags: {self.tags}" diff --git a/book_manager/requirements.txt b/book_manager/requirements.txt index 300ea5c9d..ceb315db0 100644 --- a/book_manager/requirements.txt +++ b/book_manager/requirements.txt @@ -1 +1 @@ -pyqt5 +pyqt5 diff --git a/broken_linkfinder/README.md b/broken_linkfinder/README.md index b6683cb66..d29003800 100644 --- a/broken_linkfinder/README.md +++ b/broken_linkfinder/README.md @@ -1,23 +1,23 @@ -# Broken Link Finder - -Script helps to identify each hyperlink in a website if it leads somewhere or is broken i.e. ends up at "ERROR 404: Page not found" page
-The website which needs to be searched for a broken link is provided as an argument to the script while running. - -## Setup and activate virtual environment - -For Unix based systems please execute the following command to create venv and install requirements. - -``` -make init -source .venv/bin/activate -``` - -## Usage - -``` -python broken_linkfinder.py [url] -``` - -## Example - -![Capture.png](Capture.png) +# Broken Link Finder + +Script helps to identify each hyperlink in a website if it leads somewhere or is broken i.e. ends up at "ERROR 404: Page not found" page
+The website which needs to be searched for a broken link is provided as an argument to the script while running. + +## Setup and activate virtual environment + +For Unix based systems please execute the following command to create venv and install requirements. + +``` +make init +source .venv/bin/activate +``` + +## Usage + +``` +python broken_linkfinder.py [url] +``` + +## Example + +![Capture.png](Capture.png) diff --git a/broken_linkfinder/broken_linkfinder.py b/broken_linkfinder/broken_linkfinder.py index d50ee239f..b48f21fa2 100644 --- a/broken_linkfinder/broken_linkfinder.py +++ b/broken_linkfinder/broken_linkfinder.py @@ -1,43 +1,43 @@ -import requests -import sys -from bs4 import BeautifulSoup -from urllib.parse import urlparse -from urllib.parse import urljoin - -searched_links = [] -broken_links = [] - - -def getLinksFromHTML(html): - def getLink(el): - return el["href"] - return list(map(getLink, BeautifulSoup(html, features="html.parser").select("a[href]"))) - - -def find_broken_links(domainToSearch, URL, parentURL): - if (not (URL in searched_links)) and (not URL.startswith("mailto:")) and (not ("javascript:" in URL)) and \ - (not URL.endswith(".png")) and (not URL.endswith(".jpg")) and (not URL.endswith(".jpeg")): - try: - requestObj = requests.get(URL) - searched_links.append(URL) - if(requestObj.status_code == 404): - broken_links.append("BROKEN: link " + URL + " from " + parentURL) - print(broken_links[-1]) - else: - # comment this line if you want to print only broken links - print("NOT BROKEN: link " + URL + " from " + parentURL) - if urlparse(URL).netloc == domainToSearch: - for link in getLinksFromHTML(requestObj.text): - find_broken_links(domainToSearch, urljoin(URL, link), URL) - except Exception as e: - print("ERROR: " + str(e)) - searched_links.append(domainToSearch) - - -find_broken_links(urlparse(sys.argv[1]).netloc, sys.argv[1], "") - -print("\n--- DONE! ---\n") -print("The following links were broken:") - -for link in broken_links: - print("\t" + link) +import requests +import sys +from bs4 import BeautifulSoup +from urllib.parse import urlparse +from urllib.parse import urljoin + +searched_links = [] +broken_links = [] + + +def getLinksFromHTML(html): + def getLink(el): + return el["href"] + return list(map(getLink, BeautifulSoup(html, features="html.parser").select("a[href]"))) + + +def find_broken_links(domainToSearch, URL, parentURL): + if (not (URL in searched_links)) and (not URL.startswith("mailto:")) and (not ("javascript:" in URL)) and \ + (not URL.endswith(".png")) and (not URL.endswith(".jpg")) and (not URL.endswith(".jpeg")): + try: + requestObj = requests.get(URL) + searched_links.append(URL) + if(requestObj.status_code == 404): + broken_links.append("BROKEN: link " + URL + " from " + parentURL) + print(broken_links[-1]) + else: + # comment this line if you want to print only broken links + print("NOT BROKEN: link " + URL + " from " + parentURL) + if urlparse(URL).netloc == domainToSearch: + for link in getLinksFromHTML(requestObj.text): + find_broken_links(domainToSearch, urljoin(URL, link), URL) + except Exception as e: + print("ERROR: " + str(e)) + searched_links.append(domainToSearch) + + +find_broken_links(urlparse(sys.argv[1]).netloc, sys.argv[1], "") + +print("\n--- DONE! ---\n") +print("The following links were broken:") + +for link in broken_links: + print("\t" + link) diff --git a/broken_linkfinder/makefile b/broken_linkfinder/makefile index e78e53c81..7aafa604a 100644 --- a/broken_linkfinder/makefile +++ b/broken_linkfinder/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/broken_linkfinder/requirements.txt b/broken_linkfinder/requirements.txt index a98ae430c..656175328 100644 --- a/broken_linkfinder/requirements.txt +++ b/broken_linkfinder/requirements.txt @@ -1,2 +1,2 @@ -requests +requests beautifulsoup4 \ No newline at end of file diff --git a/bulk_renamer/README.md b/bulk_renamer/README.md index c84353c5f..05ed3655a 100644 --- a/bulk_renamer/README.md +++ b/bulk_renamer/README.md @@ -1,31 +1,31 @@ -# Bulk Renamer - -Basic script for renaming files in bulk. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## No prerequisite - -## How to use - -`py bulk_renamer.py C:\\path\\to\\your\\folder new_name` - -or - -`py bulk_renamer.py C:/path/to/your/folder new_name` - -### Example - -`py bulk_renamer.py C:/my/path Baguette` - -Old name | New Name ---- | --- -Lorem.txt | Baguette - (0).txt -Ipsum.jpg | Baguette - (1).jpg -Dolores.png | Baguette - (2).png +# Bulk Renamer + +Basic script for renaming files in bulk. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## No prerequisite + +## How to use + +`py bulk_renamer.py C:\\path\\to\\your\\folder new_name` + +or + +`py bulk_renamer.py C:/path/to/your/folder new_name` + +### Example + +`py bulk_renamer.py C:/my/path Baguette` + +Old name | New Name +--- | --- +Lorem.txt | Baguette - (0).txt +Ipsum.jpg | Baguette - (1).jpg +Dolores.png | Baguette - (2).png Lers.txt | Baguette - (3).txt \ No newline at end of file diff --git a/bulk_renamer/bulk_renamer.py b/bulk_renamer/bulk_renamer.py index 5dd537a07..a5cbd4175 100644 --- a/bulk_renamer/bulk_renamer.py +++ b/bulk_renamer/bulk_renamer.py @@ -1,30 +1,30 @@ -import os -import sys - - -def add_end_slash(path): - if path[-1] != "\\" or path[-1] != "/": - return path + "\\" - - -def handle_ext(filename): - if (len(filename.split(".")) > 1): - return filename.split(".")[-1] - else: - return "" - - -def main(path, new_name): - path = add_end_slash(path) - - for count, filename in enumerate(os.listdir(path)): - - src = path + filename - ext = handle_ext(filename) - dst = f"{path}{new_name} - ({str(count)}).{ext}" - - os.rename(src, dst) - - -if __name__ == "__main__": - main(sys.argv[1], sys.argv[2]) +import os +import sys + + +def add_end_slash(path): + if path[-1] != "\\" or path[-1] != "/": + return path + "\\" + + +def handle_ext(filename): + if (len(filename.split(".")) > 1): + return filename.split(".")[-1] + else: + return "" + + +def main(path, new_name): + path = add_end_slash(path) + + for count, filename in enumerate(os.listdir(path)): + + src = path + filename + ext = handle_ext(filename) + dst = f"{path}{new_name} - ({str(count)}).{ext}" + + os.rename(src, dst) + + +if __name__ == "__main__": + main(sys.argv[1], sys.argv[2]) diff --git a/bulk_renamer/makefile b/bulk_renamer/makefile index e78e53c81..7aafa604a 100644 --- a/bulk_renamer/makefile +++ b/bulk_renamer/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/bulkemail_sender/README.md b/bulkemail_sender/README.md index 4a3569b52..7a3d501c8 100644 --- a/bulkemail_sender/README.md +++ b/bulkemail_sender/README.md @@ -1,21 +1,21 @@ -# Bulk Email Sender - -### Getting started - - -- To begin with you will have to download the required module. You can do this by doing: - `pip3 install -r requirements` or `pip install -r requirements` - -- The script supports .xlsx files. You can add all the emails in excel in this format: - ![Img](./images/img1.png) -- Note that you will have to keep the excel sheet in the same directory as your python script - -- Before executing the program you will have to allow less secure apps in your google account settings. It falls under the security settings - -- After executing the program it will ask you for: - 1) Your Email - 2) Your Password - 3) The body of the message - 4) The subject of the message - - +# Bulk Email Sender + +### Getting started + + +- To begin with you will have to download the required module. You can do this by doing: + `pip3 install -r requirements` or `pip install -r requirements` + +- The script supports .xlsx files. You can add all the emails in excel in this format: + ![Img](./images/img1.png) +- Note that you will have to keep the excel sheet in the same directory as your python script + +- Before executing the program you will have to allow less secure apps in your google account settings. It falls under the security settings + +- After executing the program it will ask you for: + 1) Your Email + 2) Your Password + 3) The body of the message + 4) The subject of the message + + diff --git a/bulkemail_sender/main.py b/bulkemail_sender/main.py index e37e52530..af1708d5c 100644 --- a/bulkemail_sender/main.py +++ b/bulkemail_sender/main.py @@ -1,17 +1,17 @@ -import pandas as pb -import smtplib -import getpass - - -e = pb.read_excel('list.xlsx') -emails = e['Emails'].values -server = smtplib.SMTP("smtp.gmail.com", 587) -server.starttls() -emailid = input("Enter your email id here: ") -server.login(emailid, getpass.getpass(prompt='Password: ')) -msg = input("Enter the body message here: ") -subject = input('Enter the subject of the message here: ') -body = 'Subject: {}\n\n{}'.format(subject, msg) -for email in emails: - server.sendmail(emailid, email, body) -server.quit() +import pandas as pb +import smtplib +import getpass + + +e = pb.read_excel('list.xlsx') +emails = e['Emails'].values +server = smtplib.SMTP("smtp.gmail.com", 587) +server.starttls() +emailid = input("Enter your email id here: ") +server.login(emailid, getpass.getpass(prompt='Password: ')) +msg = input("Enter the body message here: ") +subject = input('Enter the subject of the message here: ') +body = 'Subject: {}\n\n{}'.format(subject, msg) +for email in emails: + server.sendmail(emailid, email, body) +server.quit() diff --git a/captcha_solver/README.md b/captcha_solver/README.md index 80cdc3562..7c8a1c91d 100644 --- a/captcha_solver/README.md +++ b/captcha_solver/README.md @@ -1,28 +1,28 @@ -# Captcha Solver -A simple python script for solving simple captchas - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## Modules Used - -- pytesseract -- sys -- os -- PIL - -## Requirements - -- tesseract -`You can download tesseract from https://tesseract-ocr.github.io/tessdoc/Home.html` -- pytesseract - -- After you install tesseract replace with your tesseract location in csolver.py - -## How to use -`python csolver.py captcha_image` - +# Captcha Solver +A simple python script for solving simple captchas + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## Modules Used + +- pytesseract +- sys +- os +- PIL + +## Requirements + +- tesseract +`You can download tesseract from https://tesseract-ocr.github.io/tessdoc/Home.html` +- pytesseract + +- After you install tesseract replace with your tesseract location in csolver.py + +## How to use +`python csolver.py captcha_image` + diff --git a/captcha_solver/csolver.py b/captcha_solver/csolver.py index 6abcb1300..f9b1e37ab 100644 --- a/captcha_solver/csolver.py +++ b/captcha_solver/csolver.py @@ -1,33 +1,33 @@ -import pytesseract -import sys -import os -from PIL import Image - -# Set Tesseract location -pytesseract.pytesseract.tesseract_cmd = "" - -# Image -im = sys.argv[1] - - -def resize_image(img): - img = Image.open(img) - img = img.resize((1000, 500), Image.NEAREST) - img.save("resized.png") - - -def solve(img): - resize_image(img) - cr = pytesseract.image_to_string("resized.png") - os.remove("resized.png") - # First resize captcha and try to read it. - if cr != "\x0c": - print(cr) - else: - # If it can't read try to read in normal size - cr = pytesseract.image_to_string(im) - print(cr) - - -# Run -solve(im) +import pytesseract +import sys +import os +from PIL import Image + +# Set Tesseract location +pytesseract.pytesseract.tesseract_cmd = "" + +# Image +im = sys.argv[1] + + +def resize_image(img): + img = Image.open(img) + img = img.resize((1000, 500), Image.NEAREST) + img.save("resized.png") + + +def solve(img): + resize_image(img) + cr = pytesseract.image_to_string("resized.png") + os.remove("resized.png") + # First resize captcha and try to read it. + if cr != "\x0c": + print(cr) + else: + # If it can't read try to read in normal size + cr = pytesseract.image_to_string(im) + print(cr) + + +# Run +solve(im) diff --git a/captcha_solver/makefile b/captcha_solver/makefile index e78e53c81..7aafa604a 100644 --- a/captcha_solver/makefile +++ b/captcha_solver/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/captcha_solver/requirements.txt b/captcha_solver/requirements.txt index 9528f4962..614688df4 100644 --- a/captcha_solver/requirements.txt +++ b/captcha_solver/requirements.txt @@ -1 +1 @@ -pytesseract +pytesseract diff --git a/cfsol_submitter/README.md b/cfsol_submitter/README.md index 22213f788..f5d3dfdf7 100644 --- a/cfsol_submitter/README.md +++ b/cfsol_submitter/README.md @@ -1,43 +1,43 @@ -# CF autosubmit (Headless version) - -* This script will autmatically submit your code for the **Codeforces problems**. -* This version will work for **Chrome** users only (other browsers coming soon!). - -## Presetup zone - -* Go through the **requirements.txt** file to make sure you have the required libraries. - -* Download chromedriver zip file according to your chrome version (you can check your chrome version on - `chrome://version`) from [here](https://chromedriver.chromium.org/downloads). Make sure you save the chromedriver folder in which all your python files are stored after you downloaded python. (For ex: The path for a windows user might look like:- `C:\Python\Chromedriver`) - - -## Setup Zone - -### One time settings - -As soon as you get hold of the script, you need to make some changes according to your device to make the flow smoother everytime you run this script. - -1. Enter your username and Password within the `""` in the `headless.py` file. - -2. Select your preferred language from the `language.txt` file and if required write your langauge in the `""` of the `headless.py` file. The default has been set to `GNU G++17 7.3.0`. So C++ users may skip this step :) - -3. Head to `chrome://version` and copy the path given in heading of **Profile path** and paste it in place of: -`options.add_argument(r"C:\Users\Divyansh Mishra\AppData\Local\Google\Chrome\User Data\Default")` in the `headless.py` file. Mention your profile path in place of `C:\Users\Divyansh Mishra\AppData\Local\Google\Chrome\User Data\Default`. - -4. Head towards the chromedriver path from the folder where you saved it and paste it in place of:`driver = webdriver.Chrome('C:\Python\Chromedriver\chromedriver.exe')` in your `headless.py` file. You need to make changes in `C:\Python\Chromedriver\chromedriver.exe` part of the code. Do not tamper the remaining part of the line. - - -## Running the script - -Now that you have made all changes according to your device, a few tips: - -* Keep this script in the same folder where your codes for the CodeForces problems are saved. -* This script has been written for practice problemset, in order to use it for contests you need to make the changes: `driver.get('link for your problem'/+st)`. Now run the script from the terminal. - -* The script will ask you to enter your problem code: For example:- 1029C or 69D -* Next you need to enter the saved file, for example: 1029C.py or 69D.cpp -* Hit enter and solve the next question now :) -* This sript will submit your code in the background and send you a screenshot of the task done. -* The screenshot will be saved in the same folder as that of this script. - -#### For any issues regarding this PR feel free to contact me ! +# CF autosubmit (Headless version) + +* This script will autmatically submit your code for the **Codeforces problems**. +* This version will work for **Chrome** users only (other browsers coming soon!). + +## Presetup zone + +* Go through the **requirements.txt** file to make sure you have the required libraries. + +* Download chromedriver zip file according to your chrome version (you can check your chrome version on + `chrome://version`) from [here](https://chromedriver.chromium.org/downloads). Make sure you save the chromedriver folder in which all your python files are stored after you downloaded python. (For ex: The path for a windows user might look like:- `C:\Python\Chromedriver`) + + +## Setup Zone + +### One time settings + +As soon as you get hold of the script, you need to make some changes according to your device to make the flow smoother everytime you run this script. + +1. Enter your username and Password within the `""` in the `headless.py` file. + +2. Select your preferred language from the `language.txt` file and if required write your langauge in the `""` of the `headless.py` file. The default has been set to `GNU G++17 7.3.0`. So C++ users may skip this step :) + +3. Head to `chrome://version` and copy the path given in heading of **Profile path** and paste it in place of: +`options.add_argument(r"C:\Users\Divyansh Mishra\AppData\Local\Google\Chrome\User Data\Default")` in the `headless.py` file. Mention your profile path in place of `C:\Users\Divyansh Mishra\AppData\Local\Google\Chrome\User Data\Default`. + +4. Head towards the chromedriver path from the folder where you saved it and paste it in place of:`driver = webdriver.Chrome('C:\Python\Chromedriver\chromedriver.exe')` in your `headless.py` file. You need to make changes in `C:\Python\Chromedriver\chromedriver.exe` part of the code. Do not tamper the remaining part of the line. + + +## Running the script + +Now that you have made all changes according to your device, a few tips: + +* Keep this script in the same folder where your codes for the CodeForces problems are saved. +* This script has been written for practice problemset, in order to use it for contests you need to make the changes: `driver.get('link for your problem'/+st)`. Now run the script from the terminal. + +* The script will ask you to enter your problem code: For example:- 1029C or 69D +* Next you need to enter the saved file, for example: 1029C.py or 69D.cpp +* Hit enter and solve the next question now :) +* This sript will submit your code in the background and send you a screenshot of the task done. +* The screenshot will be saved in the same folder as that of this script. + +#### For any issues regarding this PR feel free to contact me ! diff --git a/colorimage_bw/README.md b/colorimage_bw/README.md index ece5ac3aa..7f3dfe9f3 100644 --- a/colorimage_bw/README.md +++ b/colorimage_bw/README.md @@ -1,24 +1,24 @@ -# Script to convert coloured images to black and white - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## How to use: -1. Make the directory structure as shown below: -
. -
β”œβ”€β”€ colour_to_bw.py -
└── image.png - -2. Call the function giving two arguments, the path to the original image and the path for your output image -
example :- -
```colour_to_bw("./image.png","./")``` - -3. The output of the script will be stored as "final_image.png". The directory structure would look similar to this if you execute the code in step 2. -
. -
β”œβ”€β”€ colour_to_bw.py -
β”œβ”€β”€ final_image.png -
└── ptr_mail.apng +# Script to convert coloured images to black and white + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## How to use: +1. Make the directory structure as shown below: +
. +
β”œβ”€β”€ colour_to_bw.py +
└── image.png + +2. Call the function giving two arguments, the path to the original image and the path for your output image +
example :- +
```colour_to_bw("./image.png","./")``` + +3. The output of the script will be stored as "final_image.png". The directory structure would look similar to this if you execute the code in step 2. +
. +
β”œβ”€β”€ colour_to_bw.py +
β”œβ”€β”€ final_image.png +
└── ptr_mail.apng diff --git a/colorimage_bw/colour_to_bw.py b/colorimage_bw/colour_to_bw.py index fd744d262..30e9bb891 100644 --- a/colorimage_bw/colour_to_bw.py +++ b/colorimage_bw/colour_to_bw.py @@ -1,12 +1,12 @@ -import cv2 - - -def colour_to_bw(original_image_path, output_path): - ''' - Function to convert colour image to black and white - ''' - original_image = cv2.imread(original_image_path) - gray_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY) - thresh = 128 - img_bw = cv2.threshold(gray_img, thresh, 255, cv2.THRESH_BINARY)[1] - cv2.imwrite(output_path + 'final_image.png', img_bw) +import cv2 + + +def colour_to_bw(original_image_path, output_path): + ''' + Function to convert colour image to black and white + ''' + original_image = cv2.imread(original_image_path) + gray_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY) + thresh = 128 + img_bw = cv2.threshold(gray_img, thresh, 255, cv2.THRESH_BINARY)[1] + cv2.imwrite(output_path + 'final_image.png', img_bw) diff --git a/colorimage_bw/makefile b/colorimage_bw/makefile index e78e53c81..7aafa604a 100644 --- a/colorimage_bw/makefile +++ b/colorimage_bw/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/competitive_calendar/README.md b/competitive_calendar/README.md index b700b8f74..c1c90a1eb 100644 --- a/competitive_calendar/README.md +++ b/competitive_calendar/README.md @@ -1,93 +1,93 @@ - -# Competitive Calendar - - -Get a list of all competitive programming contests happening on various sites. - -### Supported Sites -- [AtCoder](https://atcoder.jp/) -- [CodeChef](https://codechef.com/) -- [CodeForces](https://codeforces.com/) -- [CodeForces::Gym](https://codeforces.com/gyms) -- [CS Academy](https://csacademy.com/) -- [HackerEarth](https://hackerearth.com/) -- [HackerRank](https://hackerrank.com/) -- [Kick Start](https://codingcompetitions.withgoogle.com/kickstart) -- [LeetCode](https://leetcode.com/) -- [TopCoder](https://topcoder.com/) - -## Setup and activate virtual environment - -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` -For Windows users, please execute the following command to create and activate venv. -``` -virtualenv venv -"venv/Scripts/activate" -``` -Navigate back to the main folder and install the requirements. -``` -pip install -r requirements.txt -``` -## How to use - -```bash -$ python main.py [-h] [--today] -``` -If not adding any argument, the script will print all the ongoing and future contests by default. -``` -optional arguments: - --h, --help show this help message and exit ---today Print only today's contests -``` - -## Sample Output -``` -$ python main.py - -Today (13 Oct '20): - - #DeveloperIPL Game [HackerEarth] - 06:00 PM, 09 Oct '20 - 06:00 PM, 25 Oct '20 - Contest URL: https://www.hackerearth.com/challenges/hackathon/developeripl-game/ - - ProjectEuler+ [HackerRank] - 09:08 PM, 07 Jul '14 - 12:00 AM, 31 Jul '24 - Contest URL: https://hackerrank.com/contests/projecteuler - - DSA Learning Series [CodeChef] - 12:00 AM, 30 Mar '20 - 12:00 AM, 30 Mar '21 - Contest URL: https://www.codechef.com/LEARNDSA?itm_campaign=contest_listing - - -15 October, 2020: - - Hackccelerate 2020 [HackerEarth] - 11:55 PM, 15 Oct '20 - 11:55 PM, 18 Oct '20 - Contest URL: https://www.hackerearth.com/challenges/hackathon/hackccelerate-2020/ - - -17 October, 2020: - - Code Divas Diversity Challenge 2020 [HackerEarth] - 04:00 PM, 17 Oct '20 - 10:00 PM, 17 Oct '20 - Contest URL: https://www.hackerearth.com/challenges/hiring/code-divas-2020/ - - Codeforces Round (Div. 1 + Div. 2) [CodeForces] - 06:35 PM, 17 Oct '20 - 09:05 PM, 17 Oct '20 - Contest URL: https://codeforces.com/contestRegistration/1428 - - ... - ... - ... -``` - -### Credits -Thanks to [Kontests](https://github.com/AliOsm/kontests) for their free API which fetches competitive contests details from the above listed sites. - -### Contact + +# Competitive Calendar + + +Get a list of all competitive programming contests happening on various sites. + +### Supported Sites +- [AtCoder](https://atcoder.jp/) +- [CodeChef](https://codechef.com/) +- [CodeForces](https://codeforces.com/) +- [CodeForces::Gym](https://codeforces.com/gyms) +- [CS Academy](https://csacademy.com/) +- [HackerEarth](https://hackerearth.com/) +- [HackerRank](https://hackerrank.com/) +- [Kick Start](https://codingcompetitions.withgoogle.com/kickstart) +- [LeetCode](https://leetcode.com/) +- [TopCoder](https://topcoder.com/) + +## Setup and activate virtual environment + +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` +For Windows users, please execute the following command to create and activate venv. +``` +virtualenv venv +"venv/Scripts/activate" +``` +Navigate back to the main folder and install the requirements. +``` +pip install -r requirements.txt +``` +## How to use + +```bash +$ python main.py [-h] [--today] +``` +If not adding any argument, the script will print all the ongoing and future contests by default. +``` +optional arguments: + +-h, --help show this help message and exit +--today Print only today's contests +``` + +## Sample Output +``` +$ python main.py + +Today (13 Oct '20): + + #DeveloperIPL Game [HackerEarth] + 06:00 PM, 09 Oct '20 - 06:00 PM, 25 Oct '20 + Contest URL: https://www.hackerearth.com/challenges/hackathon/developeripl-game/ + + ProjectEuler+ [HackerRank] + 09:08 PM, 07 Jul '14 - 12:00 AM, 31 Jul '24 + Contest URL: https://hackerrank.com/contests/projecteuler + + DSA Learning Series [CodeChef] + 12:00 AM, 30 Mar '20 - 12:00 AM, 30 Mar '21 + Contest URL: https://www.codechef.com/LEARNDSA?itm_campaign=contest_listing + + +15 October, 2020: + + Hackccelerate 2020 [HackerEarth] + 11:55 PM, 15 Oct '20 - 11:55 PM, 18 Oct '20 + Contest URL: https://www.hackerearth.com/challenges/hackathon/hackccelerate-2020/ + + +17 October, 2020: + + Code Divas Diversity Challenge 2020 [HackerEarth] + 04:00 PM, 17 Oct '20 - 10:00 PM, 17 Oct '20 + Contest URL: https://www.hackerearth.com/challenges/hiring/code-divas-2020/ + + Codeforces Round (Div. 1 + Div. 2) [CodeForces] + 06:35 PM, 17 Oct '20 - 09:05 PM, 17 Oct '20 + Contest URL: https://codeforces.com/contestRegistration/1428 + + ... + ... + ... +``` + +### Credits +Thanks to [Kontests](https://github.com/AliOsm/kontests) for their free API which fetches competitive contests details from the above listed sites. + +### Contact Feel sure to contact [Sakshi Uppoor](https://github.com/SakshiUppoor) regarding any suggestions/bugs. \ No newline at end of file diff --git a/competitive_calendar/main.py b/competitive_calendar/main.py index 8e61751cf..ff4795811 100644 --- a/competitive_calendar/main.py +++ b/competitive_calendar/main.py @@ -1,17 +1,17 @@ -from utils import printCalendar -import argparse - -parser = argparse.ArgumentParser( - description='Get a list of all competitive programming contests happening on various sites.' -) - -parser.add_argument( - '--today', - action='store_true', - help='Print only today\'s contests' -) - -args = vars(parser.parse_args()) -today = args["today"] - -printCalendar(today) +from utils import printCalendar +import argparse + +parser = argparse.ArgumentParser( + description='Get a list of all competitive programming contests happening on various sites.' +) + +parser.add_argument( + '--today', + action='store_true', + help='Print only today\'s contests' +) + +args = vars(parser.parse_args()) +today = args["today"] + +printCalendar(today) diff --git a/competitive_calendar/makefile b/competitive_calendar/makefile index e78e53c81..7aafa604a 100644 --- a/competitive_calendar/makefile +++ b/competitive_calendar/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/competitive_calendar/requirements.txt b/competitive_calendar/requirements.txt index f86b6fd02..fc5c50ed6 100644 --- a/competitive_calendar/requirements.txt +++ b/competitive_calendar/requirements.txt @@ -1,2 +1,2 @@ -python-dateutil==2.8.1 -requests==2.24.0 +python-dateutil==2.8.1 +requests==2.24.0 diff --git a/competitive_calendar/utils.py b/competitive_calendar/utils.py index 7f04bce5e..169fbd01c 100644 --- a/competitive_calendar/utils.py +++ b/competitive_calendar/utils.py @@ -1,85 +1,85 @@ -from datetime import datetime, timedelta -from dateutil import tz -import requests - - -def get_datetime(utc_time): - """ - Convert date string to datetime object - """ - utc = datetime.strptime(utc_time, '%Y-%m-%dT%H:%M:%S.%fZ') - return utc - - -def get_local_timestamp(utc, from_zone=None): - """ - Convert 'naive' datetime object to timezone aware datetime object. - """ - if not from_zone: - from_zone = tz.tzutc() - - to_zone = tz.tzlocal() # Auto-detect zone - - utc = utc.replace(tzinfo=from_zone) - local_time = utc.astimezone(to_zone) # Convert time zone - - return local_time - - -def fetchContests(): - API_URL = "https://www.kontests.net/api/v1/all" - - req = requests.get(API_URL) - data = req.json() - return data - - -def getContests(today=False): - """ - Returns fetched contests in desired day-wise format - """ - TOMORROW = get_local_timestamp( - (datetime.today() + timedelta(days=1)) - .replace(hour=0, minute=0, second=0, microsecond=0), - from_zone=tz.tzlocal() - ) - contests = fetchContests() - calendar = {} - - for contest in contests: - local_start_time = get_local_timestamp( - get_datetime(contest["start_time"])) - local_end_time = get_local_timestamp(get_datetime(contest["end_time"])) - - contest["start_time"] = local_start_time.strftime( - "%I:%M %p, %d %b '%y") - contest["end_time"] = local_end_time.strftime( - "%I:%M %p, %d %b '%y") - - if local_end_time <= TOMORROW: # If contest has already ended, skip - continue - elif local_start_time <= TOMORROW and local_end_time > TOMORROW: - # If contest is open today - key = "Today ({})".format(datetime.today().strftime("%d %b '%y")) - else: # Future contests - if today: - return calendar - key = local_start_time.strftime("%d %B, %Y") - - if key not in calendar: - calendar[key] = [contest] - else: - calendar[key].append(contest) - - return calendar - - -def printCalendar(today): - calendar = getContests(today) - for day, contests in calendar.items(): - print(f"\n\n{day}:") - for contest in contests: - print() - print(f"\t{contest['name']} [{contest['site']}]") - print(f"\t{contest['start_time']} - {contest['end_time']}") - print(f"\tContest URL: {contest['url']}") +from datetime import datetime, timedelta +from dateutil import tz +import requests + + +def get_datetime(utc_time): + """ + Convert date string to datetime object + """ + utc = datetime.strptime(utc_time, '%Y-%m-%dT%H:%M:%S.%fZ') + return utc + + +def get_local_timestamp(utc, from_zone=None): + """ + Convert 'naive' datetime object to timezone aware datetime object. + """ + if not from_zone: + from_zone = tz.tzutc() + + to_zone = tz.tzlocal() # Auto-detect zone + + utc = utc.replace(tzinfo=from_zone) + local_time = utc.astimezone(to_zone) # Convert time zone + + return local_time + + +def fetchContests(): + API_URL = "https://www.kontests.net/api/v1/all" + + req = requests.get(API_URL) + data = req.json() + return data + + +def getContests(today=False): + """ + Returns fetched contests in desired day-wise format + """ + TOMORROW = get_local_timestamp( + (datetime.today() + timedelta(days=1)) + .replace(hour=0, minute=0, second=0, microsecond=0), + from_zone=tz.tzlocal() + ) + contests = fetchContests() + calendar = {} + + for contest in contests: + local_start_time = get_local_timestamp( + get_datetime(contest["start_time"])) + local_end_time = get_local_timestamp(get_datetime(contest["end_time"])) + + contest["start_time"] = local_start_time.strftime( + "%I:%M %p, %d %b '%y") + contest["end_time"] = local_end_time.strftime( + "%I:%M %p, %d %b '%y") + + if local_end_time <= TOMORROW: # If contest has already ended, skip + continue + elif local_start_time <= TOMORROW and local_end_time > TOMORROW: + # If contest is open today + key = "Today ({})".format(datetime.today().strftime("%d %b '%y")) + else: # Future contests + if today: + return calendar + key = local_start_time.strftime("%d %B, %Y") + + if key not in calendar: + calendar[key] = [contest] + else: + calendar[key].append(contest) + + return calendar + + +def printCalendar(today): + calendar = getContests(today) + for day, contests in calendar.items(): + print(f"\n\n{day}:") + for contest in contests: + print() + print(f"\t{contest['name']} [{contest['site']}]") + print(f"\t{contest['start_time']} - {contest['end_time']}") + print(f"\tContest URL: {contest['url']}") diff --git a/corona_tracker/README.md b/corona_tracker/README.md index ac074967e..704e8dc10 100644 --- a/corona_tracker/README.md +++ b/corona_tracker/README.md @@ -1,18 +1,18 @@ -### Covid-19 - -These scripts allows you to easily get data about current situation on Covid-19. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -#### Global script - -`python global.py` - -#### Italy script - +### Covid-19 + +These scripts allows you to easily get data about current situation on Covid-19. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +#### Global script + +`python global.py` + +#### Italy script + `python italy.py` \ No newline at end of file diff --git a/corona_tracker/global.py b/corona_tracker/global.py index a12c97ce3..b97f3e285 100755 --- a/corona_tracker/global.py +++ b/corona_tracker/global.py @@ -1,25 +1,25 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -Created on Fri Apr 10 10:46:47 2020 - -@author: edoardottt -""" - -import requests -import time -from bs4 import BeautifulSoup - -url = "https://worldometers.info/coronavirus/" -r = requests.get(url) -s = BeautifulSoup(r.text, "html.parser") -data = s.find_all("div", class_="maincounter-number") - -for x in range(0, 5): - b = "Fetching data" + "." * x - print(b, end="\r") - time.sleep(0.5) - -print("Total Cases: ", data[0].text.strip()) -print("Total Deaths: ", data[1].text.strip()) -print("Total Recovered: ", data[2].text.strip()) +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Fri Apr 10 10:46:47 2020 + +@author: edoardottt +""" + +import requests +import time +from bs4 import BeautifulSoup + +url = "https://worldometers.info/coronavirus/" +r = requests.get(url) +s = BeautifulSoup(r.text, "html.parser") +data = s.find_all("div", class_="maincounter-number") + +for x in range(0, 5): + b = "Fetching data" + "." * x + print(b, end="\r") + time.sleep(0.5) + +print("Total Cases: ", data[0].text.strip()) +print("Total Deaths: ", data[1].text.strip()) +print("Total Recovered: ", data[2].text.strip()) diff --git a/corona_tracker/italy.py b/corona_tracker/italy.py index 0e6eb7fca..6cdc5a619 100755 --- a/corona_tracker/italy.py +++ b/corona_tracker/italy.py @@ -1,136 +1,136 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -Created on Tue Mar 10 18:27:37 2020 - -@author: edoardottt -https://edoardoottavianelli.it -""" -import csv -import requests -import socket -import getopt -import sys - -CSV_URL = "https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-andamento-nazionale/\ -dpc-covid19-ita-andamento-nazionale.csv" -data = [] -mood = "" - - -# check internet connection status -def check_connection(host="8.8.8.8", port=53): - """ - Host: 8.8.8.8 (google-public-dns-a.google.com) - OpenPort: 53/tcp - Service: domain (DNS/TCP) - """ - try: - socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port)) - return True - except Exception: - print("[ERROR] Ensure you are connected to Internet.") - return False - - -# data <-- Obtaining data from CSV -def retrieve_data(CSV_URL): - print("Obtaining data...") - with requests.Session() as s: - download = s.get(CSV_URL) - decoded_content = download.content.decode("utf-8") - cr = csv.reader(decoded_content.splitlines(), delimiter=",") - my_list = list(cr) - for row in my_list: - if len(row) > 0: - data.append(row) - return data - - -options, remainder = getopt.getopt( - sys.argv[1:], "h", ["help"] -) # all the options allowed -for opt, arg in options: - if opt in ("-h", "--help"): - mood = "h" - - -def print_help(): - print("USAGE: python covid-19.py [-h]") - print("") - print(" It shows the data on the command line.") - print("") - print("-h or --help:") - print("") - print(" Help doc") - print("") - print("Use python3 if you are on Linux.") - print("") - sys.exit() - - -def increase(new_d, old_d): - diff = int(new_d) - int(old_d) - diff2 = diff / int(old_d) * 100 - if diff2 > 0: - return "+" + str(round(diff2)) + "%" - return str(round(diff2)) + "%" - - -def print_diff(title, i): - print( - " - " - + title - + ": " - + data[len(data) - 1][i] - + " (" - + increase(data[len(data) - 1][i], data[len(data) - 2][i]) - + ")" - ) - - -# PRINTING DATA ON COMMAND LINE -def print_cmd(data): - lens = [] - for i in range(len(data[2])): - temp = [data[j][i] for j in range(len(data)) if j != 0] - maxx = 0 - for elem in temp: - if len(elem) > maxx: - maxx = len(elem) - lens.append(maxx) - for i in range(len(data)): - s = "| " - for j in range(len(data[0])): - elem = data[i][j] - if j > 1: - s += elem + " " * (lens[j] - len(elem)) + " | " - else: - s += elem + " | " - print(s) - # HERE THE INCREASE FROM YESTERDAY - titles = [ - "hospitalized with symptoms", - "intensive therapy", - "total hospitalized", - "home isolation", - "total currently positives", - "total positives variation", - "new currently positives", - "discharged healed", - "deceased", - "total cases", - "swabs", - ] - print("") - print(" ### (Compared to Yesterday): ###") - for i, title in enumerate(titles): - print_diff(title, i + 2) - - -if check_connection(): - if mood == "h": - print_help() - else: - data = retrieve_data(CSV_URL) - print_cmd(data) +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Mar 10 18:27:37 2020 + +@author: edoardottt +https://edoardoottavianelli.it +""" +import csv +import requests +import socket +import getopt +import sys + +CSV_URL = "https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-andamento-nazionale/\ +dpc-covid19-ita-andamento-nazionale.csv" +data = [] +mood = "" + + +# check internet connection status +def check_connection(host="8.8.8.8", port=53): + """ + Host: 8.8.8.8 (google-public-dns-a.google.com) + OpenPort: 53/tcp + Service: domain (DNS/TCP) + """ + try: + socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port)) + return True + except Exception: + print("[ERROR] Ensure you are connected to Internet.") + return False + + +# data <-- Obtaining data from CSV +def retrieve_data(CSV_URL): + print("Obtaining data...") + with requests.Session() as s: + download = s.get(CSV_URL) + decoded_content = download.content.decode("utf-8") + cr = csv.reader(decoded_content.splitlines(), delimiter=",") + my_list = list(cr) + for row in my_list: + if len(row) > 0: + data.append(row) + return data + + +options, remainder = getopt.getopt( + sys.argv[1:], "h", ["help"] +) # all the options allowed +for opt, arg in options: + if opt in ("-h", "--help"): + mood = "h" + + +def print_help(): + print("USAGE: python covid-19.py [-h]") + print("") + print(" It shows the data on the command line.") + print("") + print("-h or --help:") + print("") + print(" Help doc") + print("") + print("Use python3 if you are on Linux.") + print("") + sys.exit() + + +def increase(new_d, old_d): + diff = int(new_d) - int(old_d) + diff2 = diff / int(old_d) * 100 + if diff2 > 0: + return "+" + str(round(diff2)) + "%" + return str(round(diff2)) + "%" + + +def print_diff(title, i): + print( + " - " + + title + + ": " + + data[len(data) - 1][i] + + " (" + + increase(data[len(data) - 1][i], data[len(data) - 2][i]) + + ")" + ) + + +# PRINTING DATA ON COMMAND LINE +def print_cmd(data): + lens = [] + for i in range(len(data[2])): + temp = [data[j][i] for j in range(len(data)) if j != 0] + maxx = 0 + for elem in temp: + if len(elem) > maxx: + maxx = len(elem) + lens.append(maxx) + for i in range(len(data)): + s = "| " + for j in range(len(data[0])): + elem = data[i][j] + if j > 1: + s += elem + " " * (lens[j] - len(elem)) + " | " + else: + s += elem + " | " + print(s) + # HERE THE INCREASE FROM YESTERDAY + titles = [ + "hospitalized with symptoms", + "intensive therapy", + "total hospitalized", + "home isolation", + "total currently positives", + "total positives variation", + "new currently positives", + "discharged healed", + "deceased", + "total cases", + "swabs", + ] + print("") + print(" ### (Compared to Yesterday): ###") + for i, title in enumerate(titles): + print_diff(title, i + 2) + + +if check_connection(): + if mood == "h": + print_help() + else: + data = retrieve_data(CSV_URL) + print_cmd(data) diff --git a/corona_tracker/makefile b/corona_tracker/makefile index e78e53c81..7aafa604a 100644 --- a/corona_tracker/makefile +++ b/corona_tracker/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/corona_tracker/requirements.txt b/corona_tracker/requirements.txt index a98ae430c..656175328 100644 --- a/corona_tracker/requirements.txt +++ b/corona_tracker/requirements.txt @@ -1,2 +1,2 @@ -requests +requests beautifulsoup4 \ No newline at end of file diff --git a/create_zip/README.md b/create_zip/README.md index 63b5f034f..8e0d87387 100644 --- a/create_zip/README.md +++ b/create_zip/README.md @@ -1,22 +1,22 @@ -### Create zip - -These scripts allows you to recursively add folder to zip file. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -```bash -make init -source .venv/bin/activate -``` - -#### Global script - -```bash -python zip.py [folder_path] -``` - -#### Configuration Options - -``` --O, --output Name of Output File -``` +### Create zip + +These scripts allows you to recursively add folder to zip file. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +```bash +make init +source .venv/bin/activate +``` + +#### Global script + +```bash +python zip.py [folder_path] +``` + +#### Configuration Options + +``` +-O, --output Name of Output File +``` diff --git a/create_zip/makefile b/create_zip/makefile index e78e53c81..7aafa604a 100644 --- a/create_zip/makefile +++ b/create_zip/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/create_zip/zip.py b/create_zip/zip.py index 62a9de1ef..88e2730b7 100644 --- a/create_zip/zip.py +++ b/create_zip/zip.py @@ -1,42 +1,42 @@ -import os -import zipfile -import argparse - - -def cli_parse(): - cli = argparse.ArgumentParser(prog='zip creator', - description='Basic automation script for \ - creating zip file from a folder') - cli.add_argument("folder", metavar='Folder', - type=str, help="Path to folder") - cli.add_argument("-o", "--output", type=str, help="Output file path") - return cli.parse_args() - - -args = cli_parse() -folder = args.folder -output = args.output - - -def zipdir(path, ziph): - # ziph is zipfile handle - for root, dirs, files in os.walk(path): - print(root, dirs, files, path) - for file in files: - ziph.write(os.path.join(root, file), - os.path.relpath(os.path.join(root, file), - os.path.join(path, '..'))) - - -# print(output) -if not output: - output = os.path.basename(folder) - -if not output.lower().endswith('.zip'): - output += ".zip" - -zipf = zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) -zipdir(folder, zipf) -zipf.close() - -print("File created", output) +import os +import zipfile +import argparse + + +def cli_parse(): + cli = argparse.ArgumentParser(prog='zip creator', + description='Basic automation script for \ + creating zip file from a folder') + cli.add_argument("folder", metavar='Folder', + type=str, help="Path to folder") + cli.add_argument("-o", "--output", type=str, help="Output file path") + return cli.parse_args() + + +args = cli_parse() +folder = args.folder +output = args.output + + +def zipdir(path, ziph): + # ziph is zipfile handle + for root, dirs, files in os.walk(path): + print(root, dirs, files, path) + for file in files: + ziph.write(os.path.join(root, file), + os.path.relpath(os.path.join(root, file), + os.path.join(path, '..'))) + + +# print(output) +if not output: + output = os.path.basename(folder) + +if not output.lower().endswith('.zip'): + output += ".zip" + +zipf = zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) +zipdir(folder, zipf) +zipf.close() + +print("File created", output) diff --git a/currency_converter/README.md b/currency_converter/README.md index 31b092920..38c189447 100644 --- a/currency_converter/README.md +++ b/currency_converter/README.md @@ -1,18 +1,18 @@ -# Currency Converter -A python script used to convert the currency of one country to that of another country. - -## Modules Used -- requests - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## How to Use -1. Setup virtual environment. -2. We are using fixer.io API for live conversion rates. Get your access key from [here](https://fixer.io/) -3. Replace **API_KEY** with your own API Key. -4. Input the countries you want to convert respectively and amount to be converted. +# Currency Converter +A python script used to convert the currency of one country to that of another country. + +## Modules Used +- requests + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## How to Use +1. Setup virtual environment. +2. We are using fixer.io API for live conversion rates. Get your access key from [here](https://fixer.io/) +3. Replace **API_KEY** with your own API Key. +4. Input the countries you want to convert respectively and amount to be converted. diff --git a/currency_converter/currency_converter.py b/currency_converter/currency_converter.py index 5aca03068..dd1863dc0 100644 --- a/currency_converter/currency_converter.py +++ b/currency_converter/currency_converter.py @@ -1,35 +1,35 @@ -# Currency Converter - -# Import necessary modules -import requests - - -class Currency_Converter: - rate = {} - - def __init__(self, url): - data = requests.get(url).json() - # Extracting rate from json - self.rate = data["rates"] - - # Conversion - def convert(self, from_country, to_country, amount): - initial = amount - if from_country != 'EUR': - amount = amount / self.rates[from_country] - - # Precision to 2 decimal places - amount = round(amount * self.rate[to_country], 2) - print(f'{initial} {from_country} = {amount} {to_country}') - - -# Driver Code -if __name__ == "__main__": - # Replace API_KEY with your own API key from fixer.io - url = 'http://data.fixer.io/api/latest?access_key=API_KEY' - cc = Currency_Converter(url) - from_country = input("From: ") - to_country = input("To: ") - amount = int(input("Amount: ")) - - cc.convert(from_country, to_country, amount) +# Currency Converter + +# Import necessary modules +import requests + + +class Currency_Converter: + rate = {} + + def __init__(self, url): + data = requests.get(url).json() + # Extracting rate from json + self.rate = data["rates"] + + # Conversion + def convert(self, from_country, to_country, amount): + initial = amount + if from_country != 'EUR': + amount = amount / self.rates[from_country] + + # Precision to 2 decimal places + amount = round(amount * self.rate[to_country], 2) + print(f'{initial} {from_country} = {amount} {to_country}') + + +# Driver Code +if __name__ == "__main__": + # Replace API_KEY with your own API key from fixer.io + url = 'http://data.fixer.io/api/latest?access_key=API_KEY' + cc = Currency_Converter(url) + from_country = input("From: ") + to_country = input("To: ") + amount = int(input("Amount: ")) + + cc.convert(from_country, to_country, amount) diff --git a/currency_converter/makefile b/currency_converter/makefile index e78e53c81..7aafa604a 100644 --- a/currency_converter/makefile +++ b/currency_converter/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/currency_converter/requirements.txt b/currency_converter/requirements.txt index f2293605c..bebaa03d1 100644 --- a/currency_converter/requirements.txt +++ b/currency_converter/requirements.txt @@ -1 +1 @@ -requests +requests diff --git a/digital_clock/README.md b/digital_clock/README.md index 8d44a440f..6b96019ee 100644 --- a/digital_clock/README.md +++ b/digital_clock/README.md @@ -1,3 +1,3 @@ -# Clock - -A digital clock app in python made with Tkinter. +# Clock + +A digital clock app in python made with Tkinter. diff --git a/digital_clock/clock.py b/digital_clock/clock.py index e9d573495..eb9480c6b 100644 --- a/digital_clock/clock.py +++ b/digital_clock/clock.py @@ -1,19 +1,19 @@ -import tkinter -from time import strftime - -top = tkinter.Tk() -top.title('Clock') -top.resizable(0, 0) - - -def time(): - string = strftime('%H:%M:%S %p') - clockTime.config(text=string) - clockTime.after(1000, time) - - -clockTime = tkinter.Label(top, font=( - 'courier new', 40,), background='black', foreground='white') -clockTime.pack(anchor='center') -time() -top.mainloop() +import tkinter +from time import strftime + +top = tkinter.Tk() +top.title('Clock') +top.resizable(0, 0) + + +def time(): + string = strftime('%H:%M:%S %p') + clockTime.config(text=string) + clockTime.after(1000, time) + + +clockTime = tkinter.Label(top, font=( + 'courier new', 40,), background='black', foreground='white') +clockTime.pack(anchor='center') +time() +top.mainloop() diff --git a/discount_alerter/Dockerfile b/discount_alerter/Dockerfile index 950bb783f..006584cf6 100644 --- a/discount_alerter/Dockerfile +++ b/discount_alerter/Dockerfile @@ -1,8 +1,8 @@ -FROM python:3.7-alpine - -COPY amazon_price.py /app/ -COPY requirements.txt /tmp -RUN pip3 install -r /tmp/requirements.txt - -WORKDIR /app +FROM python:3.7-alpine + +COPY amazon_price.py /app/ +COPY requirements.txt /tmp +RUN pip3 install -r /tmp/requirements.txt + +WORKDIR /app CMD ["python3", "amazon_price.py"] \ No newline at end of file diff --git a/discount_alerter/README.md b/discount_alerter/README.md index 84519ac94..163758355 100644 --- a/discount_alerter/README.md +++ b/discount_alerter/README.md @@ -1,51 +1,51 @@ -# Wake on discount - -## Setup and activate virtual environment: -For Unix based systems please execute the following command to create venv and install requirements. -``` -$ virtualenv .venv -$ source .venv/bin/activate -$ pip install -r requirements.txt -``` - -### Objectives -- [x] Amazon: almost Finished. - - - [x] Twillio: sends sms when the priced equals or less than desired price - -- [ ] Flipkart: Need time to invest. - -- [ ] Any Smiliar: Please [open an issue](https://github.com/python-geeks/Automation-scripts/issues/new/choose) if you want to extend the idea! - - -### Requirements -- Twilio account and API Access -- Python -- Docker :+1: - -#### USAGE: -##### Using Local/Remote machine: -This compatible with Linux and OSx -``` -$export ACCOUNT_SID="bzPFSbOiL0t3ZQ10LO1NwHHy7tAZUxZ2IuHwSYej" -$export AUTH_TOKEN="fWXgfraSQ0iOQCwkRErVa9PLb7QcjOxCRYFeCHAcX8DwjeHOG0" -$export URL="https://www.amazon.de/Web-Scraping-Python-Collecting-Modern/dp/1491985577/" -``` - -##### Using Docker-Container -Build the Docker Image -``` -docker build -t wake-on-discount . -``` - -Run the Docker Image -``` -docker run -it -e CONSUMER_KEY="" \ - -e ACCOUNT_SID="" \ - -e AUTH_TOKEN="" \ - -e URL="amazon_url" \ - wake-on-discount -``` - -suggestions: Please open an issue and tag me @ashkankamyab - +# Wake on discount + +## Setup and activate virtual environment: +For Unix based systems please execute the following command to create venv and install requirements. +``` +$ virtualenv .venv +$ source .venv/bin/activate +$ pip install -r requirements.txt +``` + +### Objectives +- [x] Amazon: almost Finished. + + - [x] Twillio: sends sms when the priced equals or less than desired price + +- [ ] Flipkart: Need time to invest. + +- [ ] Any Smiliar: Please [open an issue](https://github.com/python-geeks/Automation-scripts/issues/new/choose) if you want to extend the idea! + + +### Requirements +- Twilio account and API Access +- Python +- Docker :+1: + +#### USAGE: +##### Using Local/Remote machine: +This compatible with Linux and OSx +``` +$export ACCOUNT_SID="bzPFSbOiL0t3ZQ10LO1NwHHy7tAZUxZ2IuHwSYej" +$export AUTH_TOKEN="fWXgfraSQ0iOQCwkRErVa9PLb7QcjOxCRYFeCHAcX8DwjeHOG0" +$export URL="https://www.amazon.de/Web-Scraping-Python-Collecting-Modern/dp/1491985577/" +``` + +##### Using Docker-Container +Build the Docker Image +``` +docker build -t wake-on-discount . +``` + +Run the Docker Image +``` +docker run -it -e CONSUMER_KEY="" \ + -e ACCOUNT_SID="" \ + -e AUTH_TOKEN="" \ + -e URL="amazon_url" \ + wake-on-discount +``` + +suggestions: Please open an issue and tag me @ashkankamyab + diff --git a/discount_alerter/amazon_price.py b/discount_alerter/amazon_price.py index de767ccbc..a47ef4d0b 100644 --- a/discount_alerter/amazon_price.py +++ b/discount_alerter/amazon_price.py @@ -1,77 +1,77 @@ -#!/usr/bin/env python3 -import requests -from os import getenv -import bs4 -from twilio.rest import Client -import time - -""" -Scrapper: get_price() digs amazon URL and exracts the ProductID of it. -Product ID is the very most unique part of amazon store. -This helps to use the online portal camelcamelcamel.com. -This approache makes this script persistence. -""" - - -def get_price(URL): - country_prefix = "" - if "amazon.de" in URL: - country_prefix = "de." - URL = URL.replace("/dp/", "/product/") - - URL = URL.replace("?", "/") - ProductID = URL.split("/product/", 1)[1].split("/")[0] - - headers = { - 'authority': 'www.camelcamelcamel.com', - 'pragma': 'no-cache', - 'cache-control': 'no-cache', - 'dnt': '1', - 'upgrade-insecure-requests': '1', - 'user-agent': '''Mozilla/5.0 (X11; Chrome x86_64 8172.45.0) AppleWebKit/537.36 - (KHTML, like Gecko) Chrome/51.0.2704.64 Safari/537.36''', - 'accept': '''text/html,application/xhtml+xml,application/xml;q=0.9,image/ - webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9''', - 'sec-fetch-site': 'none', - 'sec-fetch-mode': 'navigate', - 'sec-fetch-dest': 'document', - 'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8', - } - - htmldata = requests.get("https://" + country_prefix + "camelcamelcamel.com/product/" + ProductID, headers=headers) - soup = bs4.BeautifulSoup(htmldata.text, 'html.parser') - current = ".".join(soup.find("span", {'class': 'green'}).text[:-1].split(",")) - ''' - This could be handy for futur advance comparison or maybe auto order. - # highest = ".".join(soup.find("tr", {'class': 'highest_price'}).text.strip().split("\n")[1][:-1].split(",")) - # lowest = ".".join(soup.find("tr", {'class': 'lowest_price'}).text.strip().split("\n")[1][:-1].split(",")) - ''' - return (float(current)) - - -""" -Simple Logic: Is the Product's price bellower I want, then inbox me or text me. -""" - - -def check_price(URL, desired_price): - if isinstance(desired_price) is False: - raise TypeError('Desired Price should be Int or Double decimal') - else: - current_price = (get_price(getenv("URL"))) - if(desired_price < current_price): - # TODO: Sends email - pass - if (desired_price >= current_price): - Client(getenv( - 'ACCOUNT_SID'), getenv('AUTH_TOKEN')).messages.create( - body='Current price for {} is {}.'.format(getenv("URL"), current_price), - from_='+twilio_number', - to='+user_phone_number' - ) - - -if __name__ == "__main__": - while True: - check_price(200, getenv("URL")) - time.sleep((60 * 60) * 12) +#!/usr/bin/env python3 +import requests +from os import getenv +import bs4 +from twilio.rest import Client +import time + +""" +Scrapper: get_price() digs amazon URL and exracts the ProductID of it. +Product ID is the very most unique part of amazon store. +This helps to use the online portal camelcamelcamel.com. +This approache makes this script persistence. +""" + + +def get_price(URL): + country_prefix = "" + if "amazon.de" in URL: + country_prefix = "de." + URL = URL.replace("/dp/", "/product/") + + URL = URL.replace("?", "/") + ProductID = URL.split("/product/", 1)[1].split("/")[0] + + headers = { + 'authority': 'www.camelcamelcamel.com', + 'pragma': 'no-cache', + 'cache-control': 'no-cache', + 'dnt': '1', + 'upgrade-insecure-requests': '1', + 'user-agent': '''Mozilla/5.0 (X11; Chrome x86_64 8172.45.0) AppleWebKit/537.36 + (KHTML, like Gecko) Chrome/51.0.2704.64 Safari/537.36''', + 'accept': '''text/html,application/xhtml+xml,application/xml;q=0.9,image/ + webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9''', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-dest': 'document', + 'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8', + } + + htmldata = requests.get("https://" + country_prefix + "camelcamelcamel.com/product/" + ProductID, headers=headers) + soup = bs4.BeautifulSoup(htmldata.text, 'html.parser') + current = ".".join(soup.find("span", {'class': 'green'}).text[:-1].split(",")) + ''' + This could be handy for futur advance comparison or maybe auto order. + # highest = ".".join(soup.find("tr", {'class': 'highest_price'}).text.strip().split("\n")[1][:-1].split(",")) + # lowest = ".".join(soup.find("tr", {'class': 'lowest_price'}).text.strip().split("\n")[1][:-1].split(",")) + ''' + return (float(current)) + + +""" +Simple Logic: Is the Product's price bellower I want, then inbox me or text me. +""" + + +def check_price(URL, desired_price): + if isinstance(desired_price) is False: + raise TypeError('Desired Price should be Int or Double decimal') + else: + current_price = (get_price(getenv("URL"))) + if(desired_price < current_price): + # TODO: Sends email + pass + if (desired_price >= current_price): + Client(getenv( + 'ACCOUNT_SID'), getenv('AUTH_TOKEN')).messages.create( + body='Current price for {} is {}.'.format(getenv("URL"), current_price), + from_='+twilio_number', + to='+user_phone_number' + ) + + +if __name__ == "__main__": + while True: + check_price(200, getenv("URL")) + time.sleep((60 * 60) * 12) diff --git a/discount_alerter/requirements.txt b/discount_alerter/requirements.txt index 0127c55f8..38301b48b 100644 --- a/discount_alerter/requirements.txt +++ b/discount_alerter/requirements.txt @@ -1,15 +1,15 @@ -beautifulsoup4==4.9.0 -certifi==2020.6.20 -chardet==3.0.4 -idna==2.10 -oauthlib==3.1.0 -PyJWT==1.7.1 -PySocks==1.7.1 -pytz==2020.1 -requests==2.24.0 -requests-oauthlib==1.3.0 -six==1.15.0 -soupsieve==2.0.1 -tweepy==3.9.0 -twilio==6.45.4 -urllib3==1.25.10 +beautifulsoup4==4.9.0 +certifi==2020.6.20 +chardet==3.0.4 +idna==2.10 +oauthlib==3.1.0 +PyJWT==1.7.1 +PySocks==1.7.1 +pytz==2020.1 +requests==2.24.0 +requests-oauthlib==1.3.0 +six==1.15.0 +soupsieve==2.0.1 +tweepy==3.9.0 +twilio==6.45.4 +urllib3==1.25.10 diff --git a/discount_alerter/tox.ini b/discount_alerter/tox.ini index 5f2f973a9..e0eb9ea07 100644 --- a/discount_alerter/tox.ini +++ b/discount_alerter/tox.ini @@ -1,5 +1,5 @@ -[flake8] -ignore = E226,E302,E41 -max-line-length = 119 -exclude = tests/* +[flake8] +ignore = E226,E302,E41 +max-line-length = 119 +exclude = tests/* max-complexity = 10 \ No newline at end of file diff --git a/dns_verifier/README.md b/dns_verifier/README.md index 5e5c32420..8fa83c8ca 100644 --- a/dns_verifier/README.md +++ b/dns_verifier/README.md @@ -1,26 +1,26 @@ -## DNSLU - DNS LOOK UP - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -Domain availability checker (DNS lookup) #138 - -Usage: - - python dnslu.py --dns - - -output: - - python dnslu.py --dns google.com - { - "DNS": "google.com", - "IP": [ - "172.217.172.78" - ], - "AVAIL": false +## DNSLU - DNS LOOK UP + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +Domain availability checker (DNS lookup) #138 + +Usage: + + python dnslu.py --dns + + +output: + + python dnslu.py --dns google.com + { + "DNS": "google.com", + "IP": [ + "172.217.172.78" + ], + "AVAIL": false } \ No newline at end of file diff --git a/dns_verifier/dnslu.py b/dns_verifier/dnslu.py index bfff4c65c..57a70cd14 100644 --- a/dns_verifier/dnslu.py +++ b/dns_verifier/dnslu.py @@ -1,58 +1,58 @@ -#!/usr/bin/python3 -# code: utf-8 -import json -import sys -from collections import OrderedDict - -import dns.resolver - - -def dac(dns_val=None) -> OrderedDict: - """ - Domain Availability Checker (DNS lookup) - - :param _dns: URL string - :return: Availability [True, False] - """ - ip_values = None - avail = False - - if dns_val is None: - raise ValueError("Sorry, DNS is needed") - if isinstance(dns_val, str) is False: - raise TypeError("Sorry, \'DNS\' must be type \'str\'") - try: - output = dns.resolver.resolve(dns_val, 'A') - ip_values = [ipval.to_text() for ipval in output] - except dns.resolver.NXDOMAIN: - avail = True - - return OrderedDict([ - ("DNS", dns_val), - ("IP", ip_values), - ("AVAIL", avail), - ]) - - -if __name__ == '__main__': - dns_val = None - option = None - - if len(sys.argv) > 1: - if '--dns' in sys.argv: - d_index = sys.argv.index('--dns') - if d_index == sys.argv.index(sys.argv[-1:][0]): - print("Sorry, DNS was not specified") - sys.exit(1) - dns_val = sys.argv[sys.argv.index('--dns') + 1] - else: - print("help:\nuse \'--dns\' for DNS specification") - sys.exit(1) - try: - response = dac(dns_val=dns_val) - except Exception as err: - print(f"error: {err}") - sys.exit(1) - - print(json.dumps(response, indent=4)) - sys.exit(0) +#!/usr/bin/python3 +# code: utf-8 +import json +import sys +from collections import OrderedDict + +import dns.resolver + + +def dac(dns_val=None) -> OrderedDict: + """ + Domain Availability Checker (DNS lookup) + + :param _dns: URL string + :return: Availability [True, False] + """ + ip_values = None + avail = False + + if dns_val is None: + raise ValueError("Sorry, DNS is needed") + if isinstance(dns_val, str) is False: + raise TypeError("Sorry, \'DNS\' must be type \'str\'") + try: + output = dns.resolver.resolve(dns_val, 'A') + ip_values = [ipval.to_text() for ipval in output] + except dns.resolver.NXDOMAIN: + avail = True + + return OrderedDict([ + ("DNS", dns_val), + ("IP", ip_values), + ("AVAIL", avail), + ]) + + +if __name__ == '__main__': + dns_val = None + option = None + + if len(sys.argv) > 1: + if '--dns' in sys.argv: + d_index = sys.argv.index('--dns') + if d_index == sys.argv.index(sys.argv[-1:][0]): + print("Sorry, DNS was not specified") + sys.exit(1) + dns_val = sys.argv[sys.argv.index('--dns') + 1] + else: + print("help:\nuse \'--dns\' for DNS specification") + sys.exit(1) + try: + response = dac(dns_val=dns_val) + except Exception as err: + print(f"error: {err}") + sys.exit(1) + + print(json.dumps(response, indent=4)) + sys.exit(0) diff --git a/dns_verifier/requirements.txt b/dns_verifier/requirements.txt index c186c6c3a..2168d22e9 100644 --- a/dns_verifier/requirements.txt +++ b/dns_verifier/requirements.txt @@ -1 +1 @@ -dnspython==2.0.0 +dnspython==2.0.0 diff --git a/doc_to_pdf/README.md b/doc_to_pdf/README.md index bc76a18ce..371638b03 100644 --- a/doc_to_pdf/README.md +++ b/doc_to_pdf/README.md @@ -1,16 +1,16 @@ -# Script to create wordcloud for a text file - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## How to use: -1. Call the function giving two arguments, the path to the doc file and the output path. (Include the file name that you want in the output path as well) -
example :- -
```input_file = "C:/User/Desktop/xyz.docx"``` -
```output_file = "C:/User/Desktop/xyz.pdf"``` -
```doc_to_pdf(input_file, output_file)``` - +# Script to create wordcloud for a text file + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## How to use: +1. Call the function giving two arguments, the path to the doc file and the output path. (Include the file name that you want in the output path as well) +
example :- +
```input_file = "C:/User/Desktop/xyz.docx"``` +
```output_file = "C:/User/Desktop/xyz.pdf"``` +
```doc_to_pdf(input_file, output_file)``` + diff --git a/doc_to_pdf/doc_to_pdf.py b/doc_to_pdf/doc_to_pdf.py index d7e535c88..ab945a631 100644 --- a/doc_to_pdf/doc_to_pdf.py +++ b/doc_to_pdf/doc_to_pdf.py @@ -1,10 +1,10 @@ -import comtypes.client -wdFormatPDF = 17 - - -def doc_to_pdf(input_file_path, output_file_path): - word = comtypes.client.CreateObject('Word.Application') - doc = word.Documents.Open(input_file_path) - doc.SaveAs(output_file_path, FileFormat=wdFormatPDF) - doc.Close() - word.Quit() +import comtypes.client +wdFormatPDF = 17 + + +def doc_to_pdf(input_file_path, output_file_path): + word = comtypes.client.CreateObject('Word.Application') + doc = word.Documents.Open(input_file_path) + doc.SaveAs(output_file_path, FileFormat=wdFormatPDF) + doc.Close() + word.Quit() diff --git a/doc_to_pdf/makefile b/doc_to_pdf/makefile index e78e53c81..7aafa604a 100644 --- a/doc_to_pdf/makefile +++ b/doc_to_pdf/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/duplicatefile_finder/README.md b/duplicatefile_finder/README.md index 4ad1fb851..402a4b6d8 100644 --- a/duplicatefile_finder/README.md +++ b/duplicatefile_finder/README.md @@ -1,18 +1,18 @@ -# Duplicate File Finder - - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - - -Basic script for for searching duplicate files in a folder. - -# No prerequisite - -# How to use -In the script, give absolute path of the folder in which you want to find duplicate files. +# Duplicate File Finder + + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + + +Basic script for for searching duplicate files in a folder. + +# No prerequisite + +# How to use +In the script, give absolute path of the folder in which you want to find duplicate files. you can run the file with the command ----- python file_dup.py \ No newline at end of file diff --git a/duplicatefile_finder/file_dup.py b/duplicatefile_finder/file_dup.py index 262ffa521..feddda9f2 100644 --- a/duplicatefile_finder/file_dup.py +++ b/duplicatefile_finder/file_dup.py @@ -1,80 +1,80 @@ -import os -import hashlib - -# prints duplicate files from the list - - -def show_dup_files(dup_list): - if len(dup_files) == 0: - print('no duplicate files found') - return # noqa - print('Duplicate files in the inputted directory : ') - for file_name in dup_list: - print(file_name) - -# prints out everything inside a given folder - - -def show_all_files(dest_fold): - for file_name in os.listdir(dest_fold): - print(file_name) - - -# function return hash of file content - - -def get_digest(file_path): - h = hashlib.sha256() - - with open(file_path, 'rb') as file: - while True: - # Reading is buffered, so we can read smaller chunks. - chunk = file.read(h.block_size) - if not chunk: - break - h.update(chunk) - - return h.hexdigest() - - -def get_file_hashes(file_size, size_dic, root_fold): - files = list() - files = [k for k, v in size_dic.items() if v == file_size] - hash_files = list() - hash_files = [get_digest(os.path.join(root_fold, name)) for name in files] - - return hash_files - - -if __name__ == "__main__": - try: - dest_folder = input('input the absolute path of a folder : ') - track_file_size = dict() - dup_files = list() - files_list = os.listdir(dest_folder) - for file_name in files_list: - if os.path.isdir(os.path.join(dest_folder, file_name)): - continue - - path = os.path.join(dest_folder, file_name) - file_size = os.path.getsize(path) - # searching in the dictionary - - if file_size in track_file_size.values(): - '''if it exists it may be a potential dup file - to confirm it we will hash content of both and comapare'''# noqa - # now there can be more than one files with same size so have - - files_hashed_list = get_file_hashes(file_size, track_file_size, dest_folder)# noqa - - file_hash_2 = get_digest(os.path.join(dest_folder, file_name)) - - if file_hash_2 in files_hashed_list: - dup_files.append(file_name) - else: - track_file_size[file_name] = file_size - - # show_all_files(dest_folder) - show_dup_files(dup_files) - except Exception as err: +import os +import hashlib + +# prints duplicate files from the list + + +def show_dup_files(dup_list): + if len(dup_files) == 0: + print('no duplicate files found') + return # noqa + print('Duplicate files in the inputted directory : ') + for file_name in dup_list: + print(file_name) + +# prints out everything inside a given folder + + +def show_all_files(dest_fold): + for file_name in os.listdir(dest_fold): + print(file_name) + + +# function return hash of file content + + +def get_digest(file_path): + h = hashlib.sha256() + + with open(file_path, 'rb') as file: + while True: + # Reading is buffered, so we can read smaller chunks. + chunk = file.read(h.block_size) + if not chunk: + break + h.update(chunk) + + return h.hexdigest() + + +def get_file_hashes(file_size, size_dic, root_fold): + files = list() + files = [k for k, v in size_dic.items() if v == file_size] + hash_files = list() + hash_files = [get_digest(os.path.join(root_fold, name)) for name in files] + + return hash_files + + +if __name__ == "__main__": + try: + dest_folder = input('input the absolute path of a folder : ') + track_file_size = dict() + dup_files = list() + files_list = os.listdir(dest_folder) + for file_name in files_list: + if os.path.isdir(os.path.join(dest_folder, file_name)): + continue + + path = os.path.join(dest_folder, file_name) + file_size = os.path.getsize(path) + # searching in the dictionary + + if file_size in track_file_size.values(): + '''if it exists it may be a potential dup file + to confirm it we will hash content of both and comapare'''# noqa + # now there can be more than one files with same size so have + + files_hashed_list = get_file_hashes(file_size, track_file_size, dest_folder)# noqa + + file_hash_2 = get_digest(os.path.join(dest_folder, file_name)) + + if file_hash_2 in files_hashed_list: + dup_files.append(file_name) + else: + track_file_size[file_name] = file_size + + # show_all_files(dest_folder) + show_dup_files(dup_files) + except Exception as err: print(err) # noqa \ No newline at end of file diff --git a/duplicatefile_finder/makefile b/duplicatefile_finder/makefile index e78e53c81..7aafa604a 100644 --- a/duplicatefile_finder/makefile +++ b/duplicatefile_finder/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/email_sender/README.md b/email_sender/README.md index 20131140b..7fd355115 100644 --- a/email_sender/README.md +++ b/email_sender/README.md @@ -1,71 +1,71 @@ -# EmailSender - -EmailSender a command line script and module to sending email. Using either as -a command line script or importing as a module in another python script/program - -When using EmailSender you can send an email to any recipient using a local -or remote SMTP server including authentication. Please consider security for -your local system when using. - -## Requirements -* Python 3 - -## Usage as a command line script - -The command line script has a number of options, some of which are required -and some which are not. - -```bash -usage: email_sender.py [-h] [--subject SUBJECT] [--from_email FROM_EMAIL] [--to_email TO_EMAIL] [--message MESSAGE] - [--host HOST] [--port PORT] [--starttls] [--ssl] [--username USERNAME] [--password PASSWORD] - -EmailSender - -optional arguments: - -h, --help show this help message and exit - --subject SUBJECT Subject to use in the Email message - --from_email FROM_EMAIL - Email address to use as the from address. - --to_email TO_EMAIL Email address to used to send emails too. - --msg MESSAGE Email message - --host HOST SMTP Host - --port PORT SMTP Port - --username USERNAME SMTP username - --password PASSWORD SMTP password -``` - -When running as a command line script we have two sets of options, options for -SMTP/Authentication and then the email message options. - -#### Examples - -* ***Sending an email to a local SMTP server without any authentication*** - -```bash -python email_sender.py --subject "Test Email" --from_email sam@example.com --to_email tom@example.com -``` - -* ***Sending an email using Gmail*** - -You can specify the smtp host/port along with the username/password if required by the smtp server. - -```bash -python app.py --subject test-sunday-1 --from_email sam@gmail.com --to_email tom@gmail.com --host smtp.gmail.com --port 587 --username sam@gmail.com --password PASSWORD -``` - -## Usage as a Module - -You can use this in your own code - -```python -from email_sender.email_sender import EmailSender - -# setup the object -email_sender = EmailSender() - -# send an email -email_sender.send_email(subject="Test Email", - from_email=sam@example.com, - to_email=tom@example.com, - msg="This is a test email") -``` +# EmailSender + +EmailSender a command line script and module to sending email. Using either as +a command line script or importing as a module in another python script/program + +When using EmailSender you can send an email to any recipient using a local +or remote SMTP server including authentication. Please consider security for +your local system when using. + +## Requirements +* Python 3 + +## Usage as a command line script + +The command line script has a number of options, some of which are required +and some which are not. + +```bash +usage: email_sender.py [-h] [--subject SUBJECT] [--from_email FROM_EMAIL] [--to_email TO_EMAIL] [--message MESSAGE] + [--host HOST] [--port PORT] [--starttls] [--ssl] [--username USERNAME] [--password PASSWORD] + +EmailSender + +optional arguments: + -h, --help show this help message and exit + --subject SUBJECT Subject to use in the Email message + --from_email FROM_EMAIL + Email address to use as the from address. + --to_email TO_EMAIL Email address to used to send emails too. + --msg MESSAGE Email message + --host HOST SMTP Host + --port PORT SMTP Port + --username USERNAME SMTP username + --password PASSWORD SMTP password +``` + +When running as a command line script we have two sets of options, options for +SMTP/Authentication and then the email message options. + +#### Examples + +* ***Sending an email to a local SMTP server without any authentication*** + +```bash +python email_sender.py --subject "Test Email" --from_email sam@example.com --to_email tom@example.com +``` + +* ***Sending an email using Gmail*** + +You can specify the smtp host/port along with the username/password if required by the smtp server. + +```bash +python app.py --subject test-sunday-1 --from_email sam@gmail.com --to_email tom@gmail.com --host smtp.gmail.com --port 587 --username sam@gmail.com --password PASSWORD +``` + +## Usage as a Module + +You can use this in your own code + +```python +from email_sender.email_sender import EmailSender + +# setup the object +email_sender = EmailSender() + +# send an email +email_sender.send_email(subject="Test Email", + from_email=sam@example.com, + to_email=tom@example.com, + msg="This is a test email") +``` diff --git a/email_sender/__init__.py b/email_sender/__init__.py index 49d5ebd4c..4c1547921 100644 --- a/email_sender/__init__.py +++ b/email_sender/__init__.py @@ -1,2 +1,2 @@ -__author__ = "Sam Culley" -__version__ = '0.1' +__author__ = "Sam Culley" +__version__ = '0.1' diff --git a/email_sender/email_sender.py b/email_sender/email_sender.py index 8d93a0ae1..4edda0833 100644 --- a/email_sender/email_sender.py +++ b/email_sender/email_sender.py @@ -1,155 +1,155 @@ -import smtplib -import argparse -import logging -from email.mime.multipart import MIMEMultipart -from email.mime.text import MIMEText - - -class EmailSender(object): - def __init__(self, host="localhost", port=25, username=None, - password=None): - self.host = host - self.port = port - # we can have no username/password but no host or port - self.username = username or None - self.password = password or None - # setup logging - logging.basicConfig( - format='%(asctime)s:%(levelname)s:%(name)s:%(message)s', - level=logging.INFO) - self.logger = logging.getLogger('EmailSender') - - def email_message_input(self): - """initialises a keyboard based prompt to users of the command line - script to generate the email message content used to send to the - recipient. - - :return: object contain the email message provided by the user - """ - try: - self.logger.info("Enter/Paste your email. Ctrl-D or Ctrl-Z " - "to save it") - contents = [] - while True: - try: - line = input() - except EOFError: - break - contents.append(line) - - return '\n'.join(contents) - except Exception as e: - self.logger.error(f"Unable to process email message input: {e}") - raise Exception("Unable to process email message input") - - def prepare_email(self, subject, from_email, to_email, body): - """Takes the subject, from_email, to_email and message and generates - a MIME formatted email. - - :param subject: Mail subject - :param from_email: Mail from email address - :param to_email: Mail recipient address - :param body: Message to send to recipient - - :return: MIME formatted email as a string - """ - try: - msg = MIMEMultipart() - msg['Subject'] = subject - msg['From'] = from_email - msg['To'] = to_email - msg.attach(MIMEText(body, 'plain')) - - return msg.as_string() - except Exception as error: - self.logger.error(f"Unable to prepare email message: {error}") - raise Exception("Unable to prepare email message") - - def send_email(self, subject, from_email, to_email, msg, - host=None, port=None, username=None, password=None): - """Sends an email, has the options for host, port, user/pass so you can - choose where to send an email. - - :param host: SMTP server hostname or IP - :param port: SMTP server post - :param username: Mail account username - :param password: Mail account password (sent using starttls()) - :param subject: Mail subject - :param from_email: Mail from email address - :param to_email: Mail recipient address - :param msg: Message to send to recipient - - :return: smtp sendmail response - """ - try: - host = host or self.host - port = port or self.port - username = username or self.username - password = password or self.password - - self.logger.info(f"Setting up connection to smtp://{host}:{port}") - - smtp = smtplib.SMTP(host, port) - smtp.ehlo() - smtp.starttls() - - if username and password: - smtp.login(username, password) - - email = self.prepare_email(subject, from_email, to_email, msg) - - self.logger.info(f"Sending email to: {to_email}") - return smtp.sendmail(from_email, to_email, email) - except ConnectionRefusedError: - self.logger.error(f"Error to connect to smtp://{host}:{port}") - raise Exception(f"Error to connect to smtp host: " - f"smtp://{host}:{port}") - except Exception as error: - self.logger.error(f"Unable to send email message: {error}") - raise Exception("Unable to send email message") - - -if __name__ == "__main__": - args = argparse.ArgumentParser(description="EmailSender") - args.add_argument('--subject', help="Subject to use in the Email message", - required=True) - args.add_argument('--from_email', help="Email address to use as the from" - " address.", required=True) - args.add_argument('--to_email', help="Email address to used to send emails" - " too.", required=True) - args.add_argument('--msg', help="Email message", default=None) - args.add_argument('--host', help="SMTP Host", default="localhost") - args.add_argument('--port', help="SMTP Port", default=25, type=int) - args.add_argument('--username', help="SMTP username", default=None) - args.add_argument('--password', help="SMTP password", default=None) - args = args.parse_args() - - try: - - # create the EmailSender class object, using the command line options - # as params - email_sender = EmailSender(host=args.host, - port=args.port, - username=args.username, - password=args.password) - - # set the message to the message provided in the command line options - # if specified, otherwise ask for input - if args.msg: - msg = args.msg - else: - email_sender.logger.info("Email message not provided, please " - "input now!") - msg = email_sender.email_message_input() - - # send the email - email_sender.send_email(subject=args.subject, - from_email=args.from_email, - to_email=args.to_email, - msg=msg) - - email_sender.logger.info("Email message successfully delivered") - except Exception as e: - email_sender = EmailSender() - email_sender.logger.error(f"Unable to execute the EmailSender " - f"commandline script: {e}") +import smtplib +import argparse +import logging +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText + + +class EmailSender(object): + def __init__(self, host="localhost", port=25, username=None, + password=None): + self.host = host + self.port = port + # we can have no username/password but no host or port + self.username = username or None + self.password = password or None + # setup logging + logging.basicConfig( + format='%(asctime)s:%(levelname)s:%(name)s:%(message)s', + level=logging.INFO) + self.logger = logging.getLogger('EmailSender') + + def email_message_input(self): + """initialises a keyboard based prompt to users of the command line + script to generate the email message content used to send to the + recipient. + + :return: object contain the email message provided by the user + """ + try: + self.logger.info("Enter/Paste your email. Ctrl-D or Ctrl-Z " + "to save it") + contents = [] + while True: + try: + line = input() + except EOFError: + break + contents.append(line) + + return '\n'.join(contents) + except Exception as e: + self.logger.error(f"Unable to process email message input: {e}") + raise Exception("Unable to process email message input") + + def prepare_email(self, subject, from_email, to_email, body): + """Takes the subject, from_email, to_email and message and generates + a MIME formatted email. + + :param subject: Mail subject + :param from_email: Mail from email address + :param to_email: Mail recipient address + :param body: Message to send to recipient + + :return: MIME formatted email as a string + """ + try: + msg = MIMEMultipart() + msg['Subject'] = subject + msg['From'] = from_email + msg['To'] = to_email + msg.attach(MIMEText(body, 'plain')) + + return msg.as_string() + except Exception as error: + self.logger.error(f"Unable to prepare email message: {error}") + raise Exception("Unable to prepare email message") + + def send_email(self, subject, from_email, to_email, msg, + host=None, port=None, username=None, password=None): + """Sends an email, has the options for host, port, user/pass so you can + choose where to send an email. + + :param host: SMTP server hostname or IP + :param port: SMTP server post + :param username: Mail account username + :param password: Mail account password (sent using starttls()) + :param subject: Mail subject + :param from_email: Mail from email address + :param to_email: Mail recipient address + :param msg: Message to send to recipient + + :return: smtp sendmail response + """ + try: + host = host or self.host + port = port or self.port + username = username or self.username + password = password or self.password + + self.logger.info(f"Setting up connection to smtp://{host}:{port}") + + smtp = smtplib.SMTP(host, port) + smtp.ehlo() + smtp.starttls() + + if username and password: + smtp.login(username, password) + + email = self.prepare_email(subject, from_email, to_email, msg) + + self.logger.info(f"Sending email to: {to_email}") + return smtp.sendmail(from_email, to_email, email) + except ConnectionRefusedError: + self.logger.error(f"Error to connect to smtp://{host}:{port}") + raise Exception(f"Error to connect to smtp host: " + f"smtp://{host}:{port}") + except Exception as error: + self.logger.error(f"Unable to send email message: {error}") + raise Exception("Unable to send email message") + + +if __name__ == "__main__": + args = argparse.ArgumentParser(description="EmailSender") + args.add_argument('--subject', help="Subject to use in the Email message", + required=True) + args.add_argument('--from_email', help="Email address to use as the from" + " address.", required=True) + args.add_argument('--to_email', help="Email address to used to send emails" + " too.", required=True) + args.add_argument('--msg', help="Email message", default=None) + args.add_argument('--host', help="SMTP Host", default="localhost") + args.add_argument('--port', help="SMTP Port", default=25, type=int) + args.add_argument('--username', help="SMTP username", default=None) + args.add_argument('--password', help="SMTP password", default=None) + args = args.parse_args() + + try: + + # create the EmailSender class object, using the command line options + # as params + email_sender = EmailSender(host=args.host, + port=args.port, + username=args.username, + password=args.password) + + # set the message to the message provided in the command line options + # if specified, otherwise ask for input + if args.msg: + msg = args.msg + else: + email_sender.logger.info("Email message not provided, please " + "input now!") + msg = email_sender.email_message_input() + + # send the email + email_sender.send_email(subject=args.subject, + from_email=args.from_email, + to_email=args.to_email, + msg=msg) + + email_sender.logger.info("Email message successfully delivered") + except Exception as e: + email_sender = EmailSender() + email_sender.logger.error(f"Unable to execute the EmailSender " + f"commandline script: {e}") diff --git a/email_validator/makefile b/email_validator/makefile index e78e53c81..7aafa604a 100644 --- a/email_validator/makefile +++ b/email_validator/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/emptyfolder_cleaner/makefile b/emptyfolder_cleaner/makefile index e78e53c81..7aafa604a 100644 --- a/emptyfolder_cleaner/makefile +++ b/emptyfolder_cleaner/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/excel_inspector/README.md b/excel_inspector/README.md index e440f9734..205ecc1de 100644 --- a/excel_inspector/README.md +++ b/excel_inspector/README.md @@ -1,11 +1,11 @@ -# Overall - -It provides an overview of excel spreadsheets from pandas so no need to click to open them :-) - -## What does it print? - -- It loops through each spreadsheet (.xlsx) of a folder and prints the filename -- It opens the spreadsheet and prints the total number of sheets and their names -- It parse the sheets one by one as dataframes and prints info - -### Feel free to expand on it with whatever else you would like the inspector to print out! +# Overall + +It provides an overview of excel spreadsheets from pandas so no need to click to open them :-) + +## What does it print? + +- It loops through each spreadsheet (.xlsx) of a folder and prints the filename +- It opens the spreadsheet and prints the total number of sheets and their names +- It parse the sheets one by one as dataframes and prints info + +### Feel free to expand on it with whatever else you would like the inspector to print out! diff --git a/excel_inspector/excel_inspector.py b/excel_inspector/excel_inspector.py index ab7080723..6e786ac1c 100644 --- a/excel_inspector/excel_inspector.py +++ b/excel_inspector/excel_inspector.py @@ -1,17 +1,17 @@ -# Parse spreadsheets and its sheets =========================================== -import pandas as pd -import os - -# add your folder path -sheets_folder = r'' - -for path, subdirs, files in os.walk(sheets_folder): - for filename in files: - print('\n [] File:', filename, '===============') - if filename.endswith('.xlsx'): - excel = pd.ExcelFile(path + '\\' + filename) - print('Number of sheets:', len(excel.sheet_names)) - print('Sheet names:', excel.sheet_names) - for sheet in excel.sheet_names: - df = excel.parse(sheet) - print('Sheet:', sheet, ' with the columns:', list(df.columns)) +# Parse spreadsheets and its sheets =========================================== +import pandas as pd +import os + +# add your folder path +sheets_folder = r'' + +for path, subdirs, files in os.walk(sheets_folder): + for filename in files: + print('\n [] File:', filename, '===============') + if filename.endswith('.xlsx'): + excel = pd.ExcelFile(path + '\\' + filename) + print('Number of sheets:', len(excel.sheet_names)) + print('Sheet names:', excel.sheet_names) + for sheet in excel.sheet_names: + df = excel.parse(sheet) + print('Sheet:', sheet, ' with the columns:', list(df.columns)) diff --git a/face_detection/README.md b/face_detection/README.md index 3aa172504..800f9d153 100644 --- a/face_detection/README.md +++ b/face_detection/README.md @@ -1,15 +1,15 @@ -# Detect face with openCV -Simple script to detect human face. - -# Python requirements -Python 3.0 or newer - -##How to use it -Double click on file it will open a camera window face will be detected in green box ,press q to quit the session. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate +# Detect face with openCV +Simple script to detect human face. + +# Python requirements +Python 3.0 or newer + +##How to use it +Double click on file it will open a camera window face will be detected in green box ,press q to quit the session. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate ``` \ No newline at end of file diff --git a/face_detection/haarcascade.xml b/face_detection/haarcascade.xml index 8b146217d..2248490b9 100644 --- a/face_detection/haarcascade.xml +++ b/face_detection/haarcascade.xml @@ -1,46 +1,46 @@ - - + + BOOSTHAAR2424211025<_>9-5.0426E+00<_>0 -1 0 -3.1512E-022.0875E+00 -2.2172E+00<_>0 -1 1 1.2396E-02-1.8634E+00 1.3272E+00<_>0 -1 2 2.1928E-02-1.5105E+00 1.0626E+00<_>0 -1 3 5.7530E-03-8.7464E-01 1.1760E+00<_>0 -1 4 1.5014E-02-7.7946E-01 1.2608E+00<_>0 -1 5 9.9371E-025.5751E-01 -1.8743E+00<_>0 -1 6 2.7340E-03-1.6912E+00 4.4010E-01<_>0 -1 7 -1.8859E-02-1.4770E+00 4.4350E-01<_>0 -1 8 5.9740E-03-8.5909E-01 8.5256E-01<_>16-4.9842E+00<_>0 -1 9 -2.1110E-021.2436E+00 -1.5713E+00<_>0 -1 10 2.0356E-02-1.6205E+00 1.1818E+00<_>0 -1 11 2.1309E-02-1.9416E+00 7.0069E-01<_>0 -1 12 9.1660E-02-5.5670E-01 1.7284E+00<_>0 -1 13 3.6288E-022.6764E-01 -2.1832E+00<_>0 -1 14 -1.9110E-02-2.6730E+00 4.5671E-01<_>0 -1 15 8.2540E-03-1.0853E+00 5.3564E-01<_>0 -1 16 1.8355E-02-3.5200E-01 9.3339E-01<_>0 -1 17 -7.0570E-039.2782E-01 -6.6350E-01<_>0 -1 18 -9.8770E-031.1577E+00 -2.9775E-01<_>0 -1 19 1.5814E-02-4.1961E-01 1.3576E+00<_>0 -1 20 -2.0700E-021.4590E+00 -1.9739E-01<_>0 -1 21 -1.3761E-011.1187E+00 -5.2916E-01<_>0 -1 22 1.4319E-02-3.5127E-01 1.1441E+00<_>0 -1 23 1.0253E-02-6.0851E-01 7.7099E-01<_>0 -1 24 9.1508E-023.8818E-01 -1.5123E+00<_>27-4.6552E+00<_>0 -1 25 6.9747E-02-1.0131E+00 1.4687E+00<_>0 -1 26 3.1503E-02-1.6464E+00 1.0001E+00<_>0 -1 27 1.4261E-024.6480E-01 -1.5960E+00<_>0 -1 28 1.4453E-02-6.5512E-01 8.3022E-01<_>0 -1 29 -3.0510E-03-1.3982E+00 4.2551E-01<_>0 -1 30 3.2723E-02-5.0703E-01 1.0526E+00<_>0 -1 31 -7.2960E-033.6357E-01 -1.3465E+00<_>0 -1 32 5.0425E-02-3.0461E-01 1.4504E+00<_>0 -1 33 4.6879E-02-4.0286E-01 1.2146E+00<_>0 -1 34 -6.9359E-021.0539E+00 -4.5720E-01<_>0 -1 35 -4.9034E-02-1.6253E+00 1.5379E-01<_>0 -1 36 8.4828E-022.8403E-01 -1.5662E+00<_>0 -1 37 -1.7230E-03-1.0147E+00 2.3295E-01<_>0 -1 38 1.1562E-01-1.6733E-01 1.2804E+00<_>0 -1 39 -5.1280E-021.5162E+00 -3.0271E-01<_>0 -1 40 -4.2707E-021.7632E+00 -5.1832E-02<_>0 -1 41 3.7178E-01-3.1389E-01 1.5358E+00<_>0 -1 42 1.9413E-02-1.0018E-01 9.3655E-01<_>0 -1 43 1.7439E-02-4.0380E-01 9.6293E-01<_>0 -1 44 3.9639E-021.7039E-01 -2.9603E+00<_>0 -1 45 -9.1470E-038.8787E-01 -4.3819E-01<_>0 -1 46 1.7220E-03-3.7219E-01 4.0019E-01<_>0 -1 47 3.0231E-026.5924E-02 -2.6469E+00<_>0 -1 48 -7.8796E-02-1.7491E+00 2.8475E-01<_>0 -1 49 2.1110E-03-9.3908E-01 2.3205E-01<_>0 -1 50 2.7091E-02-5.2664E-02 1.0757E+00<_>0 -1 51 -4.4965E-02-1.8294E+00 9.9562E-02<_>32-4.4532E+00<_>0 -1 52 -6.5701E-021.1559E+00 -1.0716E+00<_>0 -1 53 1.5840E-02-1.5635E+00 7.6877E-01<_>0 -1 54 1.4571E-01-5.7450E-01 1.3809E+00<_>0 -1 55 6.1390E-03-1.4571E+00 5.1610E-01<_>0 -1 56 6.7180E-03-8.3534E-01 5.8522E-01<_>0 -1 57 1.8518E-02-3.1312E-01 1.1697E+00<_>0 -1 58 1.9958E-02-4.3443E-01 9.5447E-01<_>0 -1 59 -2.7755E-011.4906E+00 -1.3816E-01<_>0 -1 60 9.1860E-03-9.6362E-01 2.7665E-01<_>0 -1 61 -3.7738E-02-2.4464E+00 2.3620E-01<_>0 -1 62 1.8463E-021.7539E-01 -1.3423E+00<_>0 -1 63 -1.1115E-024.8711E-01 -8.9852E-01<_>0 -1 64 3.3928E-021.7874E-01 -1.6342E+00<_>0 -1 65 -3.5649E-02-1.9607E+00 1.8102E-01<_>0 -1 66 -1.1438E-029.9011E-01 -3.8103E-01<_>0 -1 67 -6.5236E-02-2.5794E+00 2.4754E-01<_>0 -1 68 -4.2272E-021.4412E+00 -2.9508E-01<_>0 -1 69 1.9220E-03-4.9609E-01 6.3174E-01<_>0 -1 70 -1.2922E-01-2.3314E+00 5.4497E-02<_>0 -1 71 2.2931E-02-8.4447E-01 3.8738E-01<_>0 -1 72 -3.4120E-02-1.4432E+00 9.8423E-02<_>0 -1 73 2.6223E-021.8223E-01 -1.2587E+00<_>0 -1 74 2.2237E-026.9808E-02 -2.3821E+00<_>0 -1 75 -5.8240E-033.9333E-01 -2.7543E-01<_>0 -1 76 4.3653E-021.4833E-01 -1.1369E+00<_>0 -1 77 5.7267E-022.4628E-01 -1.2687E+00<_>0 -1 78 2.3410E-03-7.5449E-01 2.7164E-01<_>0 -1 79 1.2996E-02-3.6395E-01 7.0959E-01<_>0 -1 80 -2.6517E-02-2.3222E+00 3.5744E-02<_>0 -1 81 -5.8400E-034.2194E-01 -4.8185E-02<_>0 -1 82 -1.6569E-021.1100E+00 -3.4850E-01<_>0 -1 83 -6.8157E-02-3.3270E+00 2.1299E-01<_>52-4.3865E+00<_>0 -1 84 3.9974E-02-1.2173E+00 1.0827E+00<_>0 -1 85 1.8820E-01-4.8289E-01 1.4045E+00<_>0 -1 86 7.8027E-02-1.0782E+00 7.4040E-01<_>0 -1 87 1.1900E-04-1.2020E+00 3.7749E-01<_>0 -1 88 8.5057E-02-4.3939E-01 1.2647E+00<_>0 -1 89 8.9720E-03-1.8440E-01 4.5726E-01<_>0 -1 90 8.8120E-033.0397E-01 -9.5991E-01<_>0 -1 91 -2.3508E-021.2488E+00 4.6228E-02<_>0 -1 92 7.0040E-03-5.9442E-01 5.3963E-01<_>0 -1 93 3.3852E-022.8496E-01 -1.4895E+00<_>0 -1 94 -3.2530E-034.8121E-01 -5.2712E-01<_>0 -1 95 2.9097E-022.6744E-01 -1.6008E+00<_>0 -1 96 -8.4790E-03-1.3108E+00 1.5243E-01<_>0 -1 97 -1.0795E-024.5614E-01 -7.2051E-01<_>0 -1 98 -2.4620E-02-1.7321E+00 6.8363E-02<_>0 -1 99 3.7380E-03-1.9303E-01 6.8243E-01<_>0 -1 100 -1.2264E-02-1.6095E+00 7.5268E-02<_>0 -1 101 -4.8670E-037.4287E-01 -2.1510E-01<_>0 -1 102 7.6726E-02-2.6835E-01 1.3094E+00<_>0 -1 103 2.8578E-02-5.8793E-02 1.2196E+00<_>0 -1 104 1.9694E-02-3.5143E-01 8.4927E-01<_>0 -1 105 -2.9094E-02-1.0507E+00 2.9806E-01<_>0 -1 106 -2.9144E-028.2548E-01 -3.2687E-01<_>0 -1 107 1.9741E-022.0453E-01 -8.3760E-01<_>0 -1 108 4.3300E-032.0578E-01 -6.6830E-01<_>0 -1 109 -3.5501E-02-1.2970E+00 1.3897E-01<_>0 -1 110 -1.6173E-02-1.3111E+00 7.5752E-02<_>0 -1 111 -2.2151E-02-1.0524E+00 1.9241E-01<_>0 -1 112 -2.2707E-02-1.3735E+00 6.6781E-02<_>0 -1 113 1.6608E-02-3.7136E-02 7.7846E-01<_>0 -1 114 -1.3309E-02-9.9851E-01 1.2248E-01<_>0 -1 115 -3.3732E-021.4461E+00 1.3152E-02<_>0 -1 116 1.6935E-02-3.7121E-01 5.2842E-01<_>0 -1 117 3.3260E-03-5.7569E-01 3.9262E-01<_>0 -1 118 8.3644E-021.6116E-02 -2.1173E+00<_>0 -1 119 2.5785E-01-8.1609E-02 9.8782E-01<_>0 -1 120 -3.6567E-02-1.1512E+00 9.6459E-02<_>0 -1 121 -1.6446E-023.7315E-01 -1.4585E-01<_>0 -1 122 -3.7520E-032.6179E-01 -5.8157E-01<_>0 -1 123 -6.3660E-037.5477E-01 -1.7055E-01<_>0 -1 124 -3.8500E-032.2654E-01 -6.3876E-01<_>0 -1 125 -4.5494E-02-1.2640E+00 2.5261E-01<_>0 -1 126 -2.3941E-028.7068E-01 -2.7105E-01<_>0 -1 127 -7.7558E-02-1.3902E+00 2.3612E-01<_>0 -1 128 2.3614E-026.6140E-02 -1.2645E+00<_>0 -1 129 -2.5750E-03-5.3842E-01 3.0379E-01<_>0 -1 130 1.2011E-01-3.5343E-01 5.2866E-01<_>0 -1 131 2.2900E-03-5.8702E-01 2.4061E-01<_>0 -1 132 6.9717E-02-3.3349E-01 5.1916E-01<_>0 -1 133 -4.6670E-026.9795E-01 -1.4896E-02<_>0 -1 134 -5.0129E-028.6146E-01 -2.5986E-01<_>0 -1 135 3.0148E-021.9333E-01 -5.9131E-01<_>53-4.1299E+00<_>0 -1 136 9.1085E-02-8.9233E-01 1.0434E+00<_>0 -1 137 1.2819E-02-1.2598E+00 5.5317E-01<_>0 -1 138 1.5932E-02-8.6254E-01 6.3732E-01<_>0 -1 139 2.2780E-03-7.4639E-01 5.3156E-01<_>0 -1 140 3.1841E-02-1.2650E+00 3.6154E-01<_>0 -1 141 2.6960E-03-9.8290E-01 3.6013E-01<_>0 -1 142 -1.2055E-026.4068E-01 -5.0125E-01<_>0 -1 143 2.1325E-02-2.4035E-01 8.5448E-01<_>0 -1 144 3.0486E-02-3.4274E-01 1.1429E+00<_>0 -1 145 -4.5080E-021.0977E+00 -1.7975E-01<_>0 -1 146 -7.1701E-021.5735E+00 -3.1433E-01<_>0 -1 147 5.9218E-02-2.7582E-01 1.0449E+00<_>0 -1 148 6.7010E-03-1.0974E+00 1.9801E-01<_>0 -1 149 4.1047E-023.0548E-01 -1.3288E+00<_>0 -1 150 -8.5500E-042.5807E-01 -7.0053E-01<_>0 -1 151 -3.0360E-02-1.2306E+00 2.2609E-01<_>0 -1 152 -1.2930E-024.0759E-01 -5.1235E-01<_>0 -1 153 3.7368E-02-9.4755E-02 6.1765E-01<_>0 -1 154 2.4434E-02-4.1101E-01 4.7631E-01<_>0 -1 155 5.7008E-022.5249E-01 -6.8670E-01<_>0 -1 156 -1.6314E-02-9.3928E-01 1.1448E-01<_>0 -1 157 -1.7649E-011.2451E+00 -5.6519E-02<_>0 -1 158 1.7615E-01-3.2528E-01 8.2792E-01<_>0 -1 159 -7.3910E-033.4784E-01 -1.7929E-01<_>0 -1 160 6.0891E-025.5098E-02 -1.5481E+00<_>0 -1 161 -2.9123E-02-1.0256E+00 2.4107E-01<_>0 -1 162 -4.5649E-021.0302E+00 -3.1672E-01<_>0 -1 163 3.7333E-022.1621E-01 -8.2590E-01<_>0 -1 164 -2.4411E-02-1.5958E+00 5.1139E-02<_>0 -1 165 -5.9807E-02-1.0312E+00 1.3092E-01<_>0 -1 166 -3.0106E-02-1.4782E+00 3.7212E-02<_>0 -1 167 7.4210E-03-2.4024E-01 4.9334E-01<_>0 -1 168 -2.1910E-032.8942E-01 -5.7260E-01<_>0 -1 169 2.0861E-02-2.3148E-01 6.3766E-01<_>0 -1 170 -6.6990E-03-1.2108E+00 6.4018E-02<_>0 -1 171 1.8758E-022.4461E-01 -9.9787E-01<_>0 -1 172 -4.4323E-02-1.3699E+00 3.6052E-02<_>0 -1 173 2.2860E-022.1288E-01 -1.0398E+00<_>0 -1 174 -9.8600E-043.2444E-01 -5.4292E-01<_>0 -1 175 1.7239E-02-2.8324E-01 4.4468E-01<_>0 -1 176 -3.4531E-02-2.3107E+00 -3.1400E-03<_>0 -1 177 6.7007E-022.8716E-01 -6.4481E-01<_>0 -1 178 2.3777E-01-2.7175E-01 8.0219E-01<_>0 -1 179 -1.2903E-02-1.5318E+00 2.1424E-01<_>0 -1 180 1.0515E-027.7038E-02 -1.0581E+00<_>0 -1 181 1.6969E-021.4307E-01 -8.5828E-01<_>0 -1 182 -7.2460E-03-1.1020E+00 6.4907E-02<_>0 -1 183 1.0557E-021.3964E-02 6.3601E-01<_>0 -1 184 6.1380E-03-3.4546E-01 5.6297E-01<_>0 -1 185 1.3158E-021.9927E-01 -1.5040E+00<_>0 -1 186 3.1310E-03-4.0904E-01 3.7796E-01<_>0 -1 187 -1.0921E-01-2.2227E+00 1.2178E-01<_>0 -1 188 8.1820E-03-2.8652E-01 6.7891E-01<_>62-4.0218E+00<_>0 -1 189 3.1347E-02-8.8885E-01 9.4937E-01<_>0 -1 190 3.1918E-02-1.1147E+00 4.8889E-01<_>0 -1 191 6.5940E-03-1.0098E+00 4.9724E-01<_>0 -1 192 2.6148E-022.5991E-01 -1.2537E+00<_>0 -1 193 1.2845E-02-5.7139E-01 5.9659E-01<_>0 -1 194 2.6345E-02-5.5203E-01 3.0217E-01<_>0 -1 195 -1.5083E-02-1.2871E+00 2.2354E-01<_>0 -1 196 -3.8887E-021.7425E+00 -9.9747E-02<_>0 -1 197 -5.7030E-03-1.0523E+00 1.8363E-01<_>0 -1 198 -1.4860E-035.6784E-01 -4.6742E-01<_>0 -1 199 -2.8486E-021.3083E+00 -2.6461E-01<_>0 -1 200 6.6225E-02-4.6211E-01 4.1750E-01<_>0 -1 201 8.8570E-03-4.1475E-01 5.9205E-01<_>0 -1 202 1.1356E-023.6103E-01 -4.5781E-01<_>0 -1 203 -2.7680E-03-8.9239E-01 1.4199E-01<_>0 -1 204 1.1247E-022.9353E-01 -9.7331E-01<_>0 -1 205 7.1970E-03-7.9335E-01 1.8313E-01<_>0 -1 206 3.1769E-021.5523E-01 -1.3246E+00<_>0 -1 207 2.5174E-023.4215E-02 -2.0948E+00<_>0 -1 208 7.5360E-03-3.9451E-01 5.1334E-01<_>0 -1 209 3.2873E-028.8373E-02 -1.2814E+00<_>0 -1 210 -2.7380E-035.5287E-01 -4.6385E-01<_>0 -1 211 -3.8075E-02-1.8497E+00 4.5944E-02<_>0 -1 212 -3.8984E-02-4.8224E-01 3.4761E-01<_>0 -1 213 2.8030E-03-4.5155E-01 4.2806E-01<_>0 -1 214 -5.4146E-02-8.4521E-01 1.6675E-01<_>0 -1 215 -8.3280E-033.5348E-01 -4.7163E-01<_>0 -1 216 3.3778E-021.8463E-01 -1.6687E+00<_>0 -1 217 -1.1238E-01-1.2522E+00 3.5992E-02<_>0 -1 218 -1.0408E-02-8.1620E-01 2.3429E-01<_>0 -1 219 -4.9440E-03-9.2585E-01 1.0035E-01<_>0 -1 220 -9.3030E-035.6499E-01 -1.8882E-01<_>0 -1 221 -1.1750E-028.0302E-01 -3.8277E-01<_>0 -1 222 -2.3217E-02-8.4927E-01 1.9671E-01<_>0 -1 223 1.6866E-02-4.0592E-01 5.0695E-01<_>0 -1 224 -2.4031E-02-1.5298E+00 2.3345E-01<_>0 -1 225 -3.6946E-026.3008E-01 -3.1780E-01<_>0 -1 226 -6.1564E-025.8628E-01 -1.2108E-02<_>0 -1 227 2.1661E-02-2.5624E-01 1.0410E+00<_>0 -1 228 -3.6710E-032.9171E-01 -8.3287E-01<_>0 -1 229 4.4849E-02-3.9633E-01 4.5662E-01<_>0 -1 230 5.7195E-022.1024E-01 -1.5005E+00<_>0 -1 231 -1.1342E-024.4071E-01 -3.8654E-01<_>0 -1 232 -1.2004E-029.3955E-01 -1.0589E-01<_>0 -1 233 2.2516E-029.4480E-03 -1.6800E+00<_>0 -1 234 -1.9809E-02-1.0134E+00 2.4147E-01<_>0 -1 235 1.5891E-02-3.7508E-01 4.6614E-01<_>0 -1 236 -9.1420E-03-8.0484E-01 1.7817E-01<_>0 -1 237 -4.4740E-03-1.0562E+00 7.3305E-02<_>0 -1 238 1.2743E-012.0166E-01 -1.5468E+00<_>0 -1 239 4.7703E-02-3.7938E-01 3.7886E-01<_>0 -1 240 5.3608E-022.1220E-01 -1.2400E+00<_>0 -1 241 -3.9681E-02-1.0258E+00 5.1283E-02<_>0 -1 242 -6.7327E-02-1.0305E+00 2.3005E-01<_>0 -1 243 1.3338E-01-2.0869E-01 1.2273E+00<_>0 -1 244 -2.0919E-018.7930E-01 -4.4255E-02<_>0 -1 245 -6.5589E-021.0443E+00 -2.1682E-01<_>0 -1 246 6.1883E-021.3798E-01 -1.9009E+00<_>0 -1 247 -2.5579E-02-1.6608E+00 5.8440E-03<_>0 -1 248 -3.4827E-027.9940E-01 -8.2407E-02<_>0 -1 249 -1.8210E-02-9.6074E-01 6.6320E-02<_>0 -1 250 1.5071E-021.9899E-01 -7.6433E-01<_>72-3.8832E+00<_>0 -1 251 4.6325E-02-1.0363E+00 8.2201E-01<_>0 -1 252 1.5407E-02-1.2328E+00 2.9648E-01<_>0 -1 253 1.2809E-02-7.5852E-01 5.7986E-01<_>0 -1 254 4.9151E-02-3.8984E-01 8.9680E-01<_>0 -1 255 1.2621E-02-7.1799E-01 5.0441E-01<_>0 -1 256 -1.8769E-025.5148E-01 -7.0555E-01<_>0 -1 257 4.1965E-02-4.4782E-01 7.0986E-01<_>0 -1 258 -5.1402E-02-1.0932E+00 2.6702E-01<_>0 -1 259 -7.0961E-028.3618E-01 -3.8318E-01<_>0 -1 260 1.6746E-02-2.5733E-01 2.5967E-01<_>0 -1 261 -6.2400E-033.1631E-01 -5.8797E-01<_>0 -1 262 -3.9398E-02-1.0491E+00 1.6822E-01<_>0 -1 263 0.1.6144E-01 -8.7877E-01<_>0 -1 264 -2.2308E-02-6.9054E-01 2.3607E-01<_>0 -1 265 1.8920E-032.4989E-01 -5.6583E-01<_>0 -1 266 1.0730E-03-5.0416E-01 3.8375E-01<_>0 -1 267 3.9231E-024.2619E-02 -1.3876E+00<_>0 -1 268 6.2238E-021.4119E-01 -1.0689E+00<_>0 -1 269 2.1400E-03-8.9622E-01 1.9796E-01<_>0 -1 270 9.1800E-04-4.5337E-01 4.3533E-01<_>0 -1 271 -6.9170E-033.3823E-01 -4.4793E-01<_>0 -1 272 -2.3867E-02-7.8909E-01 2.2512E-01<_>0 -1 273 -1.0263E-01-2.2831E+00 -5.3960E-03<_>0 -1 274 -9.5240E-033.9347E-01 -5.2242E-01<_>0 -1 275 3.9877E-023.2799E-02 -1.5079E+00<_>0 -1 276 -1.3145E-02-1.0840E+00 1.8482E-01<_>0 -1 277 -5.0591E-02-1.8822E+00 -2.2200E-03<_>0 -1 278 2.4917E-021.4593E-01 -2.2197E+00<_>0 -1 279 -7.6370E-03-1.0165E+00 5.8797E-02<_>0 -1 280 4.2912E-021.5443E-01 -1.1844E+00<_>0 -1 281 2.3000E-04-7.7306E-01 1.2190E-01<_>0 -1 282 9.0930E-03-1.1450E-01 7.1091E-01<_>0 -1 283 1.1145E-027.0001E-02 -1.0535E+00<_>0 -1 284 -5.2453E-02-1.7594E+00 1.9524E-01<_>0 -1 285 -2.3021E-019.5840E-01 -2.5046E-01<_>0 -1 286 -1.6366E-024.6732E-01 -2.1108E-01<_>0 -1 287 -1.7208E-027.0836E-01 -2.8018E-01<_>0 -1 288 -3.6648E-02-1.1013E+00 2.4341E-01<_>0 -1 289 -1.0305E-02-1.0933E+00 5.6259E-02<_>0 -1 290 -1.3713E-02-2.6438E-01 1.9821E-01<_>0 -1 291 2.9308E-02-2.2142E-01 1.0526E+00<_>0 -1 292 2.4077E-021.8486E-01 -1.7204E+00<_>0 -1 293 6.1280E-03-9.2721E-01 5.8753E-02<_>0 -1 294 -2.2378E-021.9647E+00 2.7786E-02<_>0 -1 295 -7.0440E-032.1428E-01 -4.8408E-01<_>0 -1 296 -4.0603E-02-1.1754E+00 1.6061E-01<_>0 -1 297 -2.4466E-02-1.1240E+00 4.1110E-02<_>0 -1 298 2.5310E-03-1.7170E-01 3.2179E-01<_>0 -1 299 -1.9589E-028.2720E-01 -2.6377E-01<_>0 -1 300 -2.9636E-02-1.1525E+00 1.4999E-01<_>0 -1 301 -1.5030E-02-1.0492E+00 4.0161E-02<_>0 -1 302 -6.0715E-02-1.0904E+00 1.5331E-01<_>0 -1 303 -1.2790E-024.2249E-01 -4.2399E-01<_>0 -1 304 -2.0248E-02-9.1867E-01 1.8486E-01<_>0 -1 305 -3.0684E-02-1.5959E+00 2.5760E-03<_>0 -1 306 -2.0718E-02-6.6300E-01 3.1037E-01<_>0 -1 307 -1.7290E-031.9183E-01 -6.5085E-01<_>0 -1 308 -3.1394E-02-6.3643E-01 1.5408E-01<_>0 -1 309 1.9003E-02-1.8919E-01 1.5295E+00<_>0 -1 310 6.1770E-03-1.0598E-01 6.4860E-01<_>0 -1 311 -1.0166E-02-1.0803E+00 3.7176E-02<_>0 -1 312 -1.4170E-033.4157E-01 -9.7738E-02<_>0 -1 313 -4.0800E-034.7625E-01 -3.4366E-01<_>0 -1 314 -4.4097E-029.7634E-01 -1.9173E-02<_>0 -1 315 -6.0670E-02-2.1753E+00 -2.8926E-02<_>0 -1 316 -3.2932E-02-6.4383E-01 1.6494E-01<_>0 -1 317 -1.4723E-01-1.4746E+00 2.5840E-03<_>0 -1 318 -1.1930E-024.2441E-01 -1.7713E-01<_>0 -1 319 1.4518E-012.5445E-02 -1.2779E+00<_>0 -1 320 5.1448E-021.5678E-01 -1.5188E+00<_>0 -1 321 3.1480E-03-4.0424E-01 3.2430E-01<_>0 -1 322 -4.3600E-02-1.9932E+00 1.5019E-01<_>83-3.8425E+00<_>0 -1 323 1.2900E-01-6.2162E-01 1.1117E+00<_>0 -1 324 -9.1262E-021.0143E+00 -6.1335E-01<_>0 -1 325 1.4272E-02-1.0262E+00 3.9780E-01<_>0 -1 326 3.2890E-02-1.1386E+00 2.8691E-01<_>0 -1 327 1.2590E-02-5.6646E-01 4.5172E-01<_>0 -1 328 1.4661E-023.0506E-01 -6.8130E-01<_>0 -1 329 -3.3556E-02-1.7209E+00 6.1439E-02<_>0 -1 330 1.4253E-012.3192E-01 -1.7297E+00<_>0 -1 331 -6.2080E-03-1.2163E+00 1.2160E-01<_>0 -1 332 1.8179E-023.2554E-01 -8.1004E-01<_>0 -1 333 2.5037E-02-3.1699E-01 6.7361E-01<_>0 -1 334 4.6561E-02-1.1090E-01 8.4083E-01<_>0 -1 335 -9.0000E-033.9575E-01 -4.7625E-01<_>0 -1 336 4.0806E-02-1.8000E-04 9.4571E-01<_>0 -1 337 -3.4222E-027.5206E-01 -3.1532E-01<_>0 -1 338 -3.9716E-02-8.3140E-01 1.7744E-01<_>0 -1 339 2.5170E-03-5.9378E-01 2.4657E-01<_>0 -1 340 2.7429E-021.5998E-01 -4.2782E-01<_>0 -1 341 3.4986E-023.5056E-02 -1.5989E+00<_>0 -1 342 4.4970E-03-5.2034E-01 3.7828E-01<_>0 -1 343 2.7700E-03-5.3183E-01 2.4951E-01<_>0 -1 344 3.5174E-021.9983E-01 -1.4446E+00<_>0 -1 345 2.5971E-024.4427E-02 -1.3623E+00<_>0 -1 346 -1.5784E-02-9.1020E-01 2.7190E-01<_>0 -1 347 -7.5880E-039.2065E-02 -8.1629E-01<_>0 -1 348 2.0754E-022.1186E-01 -7.4729E-01<_>0 -1 349 5.9829E-02-2.7301E-01 8.0923E-01<_>0 -1 350 3.9039E-02-1.0432E-01 8.6226E-01<_>0 -1 351 2.1666E-026.2709E-02 -9.8894E-01<_>0 -1 352 -2.7497E-02-9.2691E-01 1.5586E-01<_>0 -1 353 1.0462E-021.3418E-01 -7.0386E-01<_>0 -1 354 2.4871E-021.9707E-01 -4.0263E-01<_>0 -1 355 -1.6036E-02-1.1410E+00 7.3998E-02<_>0 -1 356 4.8627E-021.6990E-01 -7.2152E-01<_>0 -1 357 1.2620E-03-4.7390E-01 2.6255E-01<_>0 -1 358 -8.8035E-02-2.1607E+00 1.4555E-01<_>0 -1 359 1.8357E-024.4751E-02 -1.0766E+00<_>0 -1 360 3.5275E-02-3.2919E-02 1.2154E+00<_>0 -1 361 -2.0393E-01-1.3188E+00 1.5504E-02<_>0 -1 362 -1.6619E-023.6850E-01 -1.5284E-01<_>0 -1 363 3.7739E-02-2.5728E-01 7.0655E-01<_>0 -1 364 2.2720E-03-7.7603E-02 3.3368E-01<_>0 -1 365 -1.4803E-02-7.8525E-01 7.6934E-02<_>0 -1 366 -4.8319E-021.7022E+00 4.9722E-02<_>0 -1 367 -2.9539E-027.7671E-01 -2.4534E-01<_>0 -1 368 -4.6169E-02-1.4923E+00 1.2340E-01<_>0 -1 369 -2.8065E-02-2.1345E+00 -2.5797E-02<_>0 -1 370 -5.7340E-035.6983E-01 -1.2057E-01<_>0 -1 371 -1.0111E-026.7911E-01 -2.6638E-01<_>0 -1 372 1.1360E-022.4790E-01 -6.4493E-01<_>0 -1 373 5.1809E-021.4716E-02 -1.2396E+00<_>0 -1 374 3.3292E-02-8.2560E-03 1.0168E+00<_>0 -1 375 -1.4494E-024.5067E-01 -3.6251E-01<_>0 -1 376 -3.4222E-02-9.5293E-01 2.0685E-01<_>0 -1 377 -8.0654E-02-2.0140E+00 -2.3085E-02<_>0 -1 378 -8.9400E-043.9572E-01 -2.9351E-01<_>0 -1 379 9.7162E-02-2.4980E-01 1.0859E+00<_>0 -1 380 3.6614E-02-5.7844E-02 1.2162E+00<_>0 -1 381 5.1694E-024.3063E-02 -1.0636E+00<_>0 -1 382 -2.4557E-02-4.8947E-01 1.7183E-01<_>0 -1 383 3.2737E-01-2.9689E-01 5.1798E-01<_>0 -1 384 7.6960E-03-5.9806E-01 2.4803E-01<_>0 -1 385 1.6172E-01-2.9614E-02 -2.3163E+00<_>0 -1 386 -4.7890E-033.7458E-01 -3.2779E-01<_>0 -1 387 -1.8403E-02-9.9693E-01 7.2948E-02<_>0 -1 388 7.7665E-021.4176E-01 -1.7239E+00<_>0 -1 389 1.8921E-02-2.1273E-01 1.0165E+00<_>0 -1 390 -7.9398E-02-1.3164E+00 1.4982E-01<_>0 -1 391 -6.8037E-024.9422E-01 -2.9091E-01<_>0 -1 392 -6.1010E-034.2430E-01 -3.3899E-01<_>0 -1 393 3.1927E-02-3.1047E-02 -2.3460E+00<_>0 -1 394 -2.9844E-02-7.8990E-01 1.5418E-01<_>0 -1 395 -8.0542E-02-2.2509E+00 -3.0907E-02<_>0 -1 396 3.8110E-03-2.5577E-01 2.3786E-01<_>0 -1 397 3.3647E-02-2.2541E-01 9.2307E-01<_>0 -1 398 8.2810E-03-2.8896E-01 3.1046E-01<_>0 -1 399 1.0104E-01-3.4864E-02 -2.7103E+00<_>0 -1 400 -1.0009E-025.9715E-01 -3.3831E-02<_>0 -1 401 7.1920E-03-4.7738E-01 2.2686E-01<_>0 -1 402 2.4969E-022.2878E-01 -1.0436E+00<_>0 -1 403 2.7908E-01-2.5818E-01 7.6780E-01<_>0 -1 404 -4.4213E-02-5.9798E-01 2.8040E-01<_>0 -1 405 -1.4137E-027.0987E-01 -2.5645E-01<_>91-3.6479E+00<_>0 -1 406 1.3771E-01-5.5871E-01 1.0954E+00<_>0 -1 407 3.4461E-02-7.1172E-01 5.2900E-01<_>0 -1 408 1.8580E-02-1.1158E+00 4.0594E-01<_>0 -1 409 2.5042E-02-4.0892E-01 7.4130E-01<_>0 -1 410 5.7179E-02-3.8054E-01 7.3648E-01<_>0 -1 411 1.4932E-02-6.9946E-01 3.7951E-01<_>0 -1 412 8.8900E-03-5.4559E-01 3.6332E-01<_>0 -1 413 3.0436E-02-1.0125E-01 7.9586E-01<_>0 -1 414 -4.4160E-028.4411E-01 -3.2976E-01<_>0 -1 415 1.8461E-022.6327E-01 -9.6737E-01<_>0 -1 416 1.0615E-021.5252E-01 -1.0590E+00<_>0 -1 417 -4.5974E-02-1.9918E+00 1.3629E-01<_>0 -1 418 8.2900E-02-3.2037E-01 6.0304E-01<_>0 -1 419 -8.9130E-035.9587E-01 -2.1140E-01<_>0 -1 420 4.2814E-022.2925E-02 -1.4679E+00<_>0 -1 421 -8.7140E-03-4.3990E-01 2.0440E-01<_>0 -1 422 -4.3390E-03-8.9067E-01 1.0470E-01<_>0 -1 423 8.0750E-032.1164E-01 -4.0232E-01<_>0 -1 424 9.6739E-021.3320E-02 -1.6085E+00<_>0 -1 425 -3.0537E-021.0064E+00 -1.3413E-01<_>0 -1 426 -6.0856E-02-1.4690E+00 9.4240E-03<_>0 -1 427 -3.8162E-02-8.1636E-01 2.6171E-01<_>0 -1 428 -9.6960E-031.1562E-01 -7.1693E-01<_>0 -1 429 4.8903E-021.3050E-01 -1.6448E+00<_>0 -1 430 -4.1612E-02-1.1796E+00 2.5017E-02<_>0 -1 431 -2.0188E-026.3188E-01 -1.0490E-01<_>0 -1 432 -9.7900E-041.8508E-01 -5.3566E-01<_>0 -1 433 -3.3622E-02-9.3128E-01 2.0072E-01<_>0 -1 434 1.9456E-023.8029E-02 -1.0112E+00<_>0 -1 435 -3.1800E-043.6458E-01 -2.7611E-01<_>0 -1 436 -3.8900E-041.9666E-01 -5.3411E-01<_>0 -1 437 -9.3496E-02-1.6772E+00 2.0727E-01<_>0 -1 438 -7.7878E-02-3.0761E+00 -3.5804E-02<_>0 -1 439 1.6948E-022.1447E-01 -7.1376E-01<_>0 -1 440 -2.1459E-02-1.1468E+00 1.5856E-02<_>0 -1 441 -1.2866E-028.3812E-01 -6.5944E-02<_>0 -1 442 7.8220E-03-2.8027E-01 7.9377E-01<_>0 -1 443 1.0294E-011.7832E-01 -6.8412E-01<_>0 -1 444 -3.7488E-029.6190E-01 -2.1736E-01<_>0 -1 445 2.5506E-021.0104E-02 1.2461E+00<_>0 -1 446 6.6700E-04-5.3488E-01 1.4746E-01<_>0 -1 447 -2.8868E-018.2173E-01 -1.4948E-02<_>0 -1 448 9.1295E-02-1.9605E-01 1.0803E+00<_>0 -1 449 1.2057E-01-2.3849E-02 1.1393E+00<_>0 -1 450 -7.3775E-02-1.3584E+00 -4.2040E-03<_>0 -1 451 -3.3128E-02-6.4483E-01 2.4142E-01<_>0 -1 452 -4.3937E-028.4285E-01 -2.0625E-01<_>0 -1 453 1.8110E-011.9212E-01 -1.2222E+00<_>0 -1 454 -1.1851E-02-7.2677E-01 5.2688E-02<_>0 -1 455 4.5920E-03-3.6305E-01 2.9224E-01<_>0 -1 456 7.0620E-035.8116E-02 -6.7162E-01<_>0 -1 457 -2.3715E-024.7142E-01 1.8580E-02<_>0 -1 458 -6.7172E-02-1.1332E+00 2.3781E-02<_>0 -1 459 -6.5310E-029.8254E-01 2.8362E-02<_>0 -1 460 2.2791E-02-2.8214E-01 5.8993E-01<_>0 -1 461 -1.9038E-02-6.3712E-01 2.6515E-01<_>0 -1 462 -6.8690E-033.7487E-01 -3.3232E-01<_>0 -1 463 -4.0146E-02-1.3049E+00 1.5724E-01<_>0 -1 464 -4.0531E-02-2.0458E+00 -2.6926E-02<_>0 -1 465 -1.2254E-027.7649E-01 -4.2971E-02<_>0 -1 466 -2.7220E-021.7424E-01 -4.4601E-01<_>0 -1 467 -8.8366E-02-1.5036E+00 1.4290E-01<_>0 -1 468 -7.9160E-032.8667E-01 -3.7924E-01<_>0 -1 469 -4.1960E-021.3847E+00 6.5027E-02<_>0 -1 470 4.5663E-02-2.2452E-01 7.9521E-01<_>0 -1 471 -1.4091E-01-1.5879E+00 1.1359E-01<_>0 -1 472 -5.9216E-02-1.1946E+00 -7.1640E-03<_>0 -1 473 4.3390E-03-1.5529E-01 4.0664E-01<_>0 -1 474 -2.0370E-032.5928E-01 -3.8368E-01<_>0 -1 475 2.7516E-01-8.8498E-02 7.6788E-01<_>0 -1 476 -2.6602E-027.5024E-01 -2.2622E-01<_>0 -1 477 4.0906E-021.2159E-01 -1.4567E+00<_>0 -1 478 5.5320E-03-3.6612E-01 2.5969E-01<_>0 -1 479 3.1879E-02-7.5019E-02 4.8485E-01<_>0 -1 480 -4.1482E-027.8220E-01 -2.1992E-01<_>0 -1 481 -9.6131E-02-8.9456E-01 1.4681E-01<_>0 -1 482 -1.1569E-028.2714E-01 -2.0276E-01<_>0 -1 483 1.8313E-021.6368E-02 2.7307E-01<_>0 -1 484 -3.4166E-021.1307E+00 -1.8811E-01<_>0 -1 485 -2.4477E-02-5.7791E-01 1.5812E-01<_>0 -1 486 4.8957E-02-2.2565E-02 -1.6373E+00<_>0 -1 487 -2.0703E-02-5.4512E-01 2.4087E-01<_>0 -1 488 -2.3002E-02-1.2237E+00 -7.3440E-03<_>0 -1 489 6.4585E-021.4696E-01 -4.4967E-01<_>0 -1 490 1.2666E-02-2.7874E-01 4.3877E-01<_>0 -1 491 -1.2003E-02-2.4289E-01 2.5350E-01<_>0 -1 492 -2.6444E-02-8.5865E-01 2.6026E-02<_>0 -1 493 -2.5548E-026.9288E-01 -2.1160E-03<_>0 -1 494 3.9115E-02-1.6589E-01 1.5209E+00<_>0 -1 495 -6.0330E-034.3857E-01 -2.1614E-01<_>0 -1 496 -3.3937E-02-9.7998E-01 2.2133E-02<_>99-3.8700E+00<_>0 -1 497 4.0673E-02-9.0475E-01 6.4411E-01<_>0 -1 498 2.5610E-02-7.9217E-01 5.7490E-01<_>0 -1 499 1.9960E-01-3.0100E-01 1.3144E+00<_>0 -1 500 1.2405E-02-8.9883E-01 2.9206E-01<_>0 -1 501 3.9208E-02-4.1955E-01 5.3463E-01<_>0 -1 502 -3.0844E-024.5793E-01 -4.4629E-01<_>0 -1 503 -3.5523E-029.1311E-01 -2.7373E-01<_>0 -1 504 -6.1650E-02-1.4698E+00 2.0364E-01<_>0 -1 505 -1.1740E-02-1.0483E+00 6.7802E-02<_>0 -1 506 6.6934E-022.9274E-01 -5.2283E-01<_>0 -1 507 -2.0631E-02-1.2855E+00 4.4551E-02<_>0 -1 508 -2.2357E-02-8.5754E-01 1.8434E-01<_>0 -1 509 1.1500E-031.6406E-01 -6.9125E-01<_>0 -1 510 3.5873E-021.5756E-01 -8.4263E-01<_>0 -1 511 3.0660E-022.1637E-02 -1.3635E+00<_>0 -1 512 5.5560E-03-1.6737E-01 2.5888E-01<_>0 -1 513 -6.1160E-03-9.7272E-01 6.6100E-02<_>0 -1 514 -3.0317E-029.8474E-01 -1.6448E-02<_>0 -1 515 -9.7200E-034.7605E-01 -3.2517E-01<_>0 -1 516 -5.7127E-02-9.5921E-01 1.9938E-01<_>0 -1 517 4.0060E-03-5.2613E-01 2.2429E-01<_>0 -1 518 3.3734E-021.7070E-01 -1.0738E+00<_>0 -1 519 -3.4642E-02-1.1343E+00 3.6540E-02<_>0 -1 520 4.6923E-022.5832E-01 -7.1536E-01<_>0 -1 521 -8.7660E-031.9641E-01 -5.3355E-01<_>0 -1 522 6.5628E-02-5.1195E-02 9.7611E-01<_>0 -1 523 -4.4165E-021.0632E+00 -2.3463E-01<_>0 -1 524 1.7305E-02-1.8583E-01 4.5890E-01<_>0 -1 525 3.3136E-02-2.9382E-02 -2.6651E+00<_>0 -1 526 -2.1030E-029.9980E-01 2.4937E-02<_>0 -1 527 2.9784E-02-2.9606E-02 -2.1696E+00<_>0 -1 528 5.5292E-02-7.5600E-04 7.4652E-01<_>0 -1 529 -3.3598E-02-1.5274E+00 1.1060E-02<_>0 -1 530 1.9603E-023.3575E-02 9.9526E-01<_>0 -1 531 -2.0787E-027.6613E-01 -2.4671E-01<_>0 -1 532 3.2536E-021.6263E-01 -6.1134E-01<_>0 -1 533 -1.0788E-02-9.7840E-01 2.8970E-02<_>0 -1 534 -9.9560E-034.6146E-01 -1.3510E-01<_>0 -1 535 -3.7490E-032.5458E-01 -5.1956E-01<_>0 -1 536 -4.1780E-02-8.0565E-01 1.5209E-01<_>0 -1 537 -3.4221E-02-1.3138E+00 -3.5800E-03<_>0 -1 538 1.0130E-022.0176E-01 -6.1340E-01<_>0 -1 539 -8.9849E-029.7633E-01 -2.0885E-01<_>0 -1 540 2.6098E-02-1.8808E-01 4.7706E-01<_>0 -1 541 -3.7540E-03-6.7980E-01 1.1289E-01<_>0 -1 542 3.1973E-021.8952E-01 -1.4967E+00<_>0 -1 543 1.9333E-02-2.3610E-01 8.1321E-01<_>0 -1 544 1.9490E-032.4830E-01 -6.9212E-02<_>0 -1 545 -4.4147E-02-1.0419E+00 4.8053E-02<_>0 -1 546 -4.4682E-025.1346E-01 -7.3800E-03<_>0 -1 547 -1.0757E-011.6202E+00 -1.8668E-01<_>0 -1 548 -1.2847E-012.9869E+00 9.5428E-02<_>0 -1 549 -4.4758E-026.0405E-01 -2.7059E-01<_>0 -1 550 -4.3991E-02-6.1791E-01 1.5997E-01<_>0 -1 551 -1.2269E-016.6327E-01 -2.3637E-01<_>0 -1 552 -1.9983E-02-1.1229E+00 1.9617E-01<_>0 -1 553 -1.5528E-02-1.0770E+00 2.0693E-02<_>0 -1 554 -4.8971E-028.1168E-01 -1.7252E-02<_>0 -1 555 5.5976E-02-2.2529E-02 -1.7357E+00<_>0 -1 556 -9.8580E-036.7881E-01 -5.8180E-02<_>0 -1 557 1.3481E-025.7848E-02 -7.7255E-01<_>0 -1 558 6.5610E-03-1.3147E-01 6.7056E-01<_>0 -1 559 7.1150E-03-3.7881E-01 3.0979E-01<_>0 -1 560 4.8160E-03-5.8470E-01 2.5602E-01<_>0 -1 561 9.5320E-03-3.0217E-01 4.1253E-01<_>0 -1 562 -2.7475E-025.9155E-01 1.7964E-02<_>0 -1 563 -3.9520E-029.6913E-01 -2.1020E-01<_>0 -1 564 -3.0659E-029.1156E-01 4.0550E-02<_>0 -1 565 -1.4680E-03-6.0490E-01 1.6961E-01<_>0 -1 566 1.9078E-014.3515E-02 8.1893E-01<_>0 -1 567 5.1790E-03-9.3617E-01 2.4937E-02<_>0 -1 568 2.4126E-021.8176E-01 -3.4186E-01<_>0 -1 569 -2.6384E-02-1.2913E+00 -3.4280E-03<_>0 -1 570 5.4140E-03-4.6292E-02 2.5270E-01<_>0 -1 571 5.4216E-02-1.2848E-02 -1.4305E+00<_>0 -1 572 2.3800E-04-2.6677E-01 3.3588E-01<_>0 -1 573 1.5217E-02-5.1367E-01 1.3005E-01<_>0 -1 574 1.7008E-024.1576E-01 -3.1241E-01<_>0 -1 575 3.0497E-02-2.4821E-01 7.0828E-01<_>0 -1 576 6.5430E-03-2.2637E-01 1.9185E-01<_>0 -1 577 1.4164E-016.5227E-02 -8.8810E-01<_>0 -1 578 1.9338E-021.8891E-01 -2.7398E-01<_>0 -1 579 -1.7324E-02-9.4867E-01 2.4197E-02<_>0 -1 580 -6.2070E-033.6938E-01 -1.7495E-01<_>0 -1 581 -1.6109E-029.6159E-01 -2.0005E-01<_>0 -1 582 -1.0123E-01-3.0699E+00 1.1364E-01<_>0 -1 583 -7.5510E-032.2921E-01 -4.5645E-01<_>0 -1 584 4.4248E-02-3.1600E-04 3.9225E-01<_>0 -1 585 -1.1636E-019.5234E-01 -2.0202E-01<_>0 -1 586 4.7360E-03-9.9177E-02 2.0370E-01<_>0 -1 587 2.2459E-028.7280E-03 -1.0217E+00<_>0 -1 588 -1.2109E-026.4813E-01 -9.0149E-02<_>0 -1 589 5.6120E-02-3.6760E-02 -1.9276E+00<_>0 -1 590 -8.7380E-036.9261E-01 -6.8375E-02<_>0 -1 591 6.6400E-03-4.0570E-01 1.8626E-01<_>0 -1 592 -1.8132E-02-6.4518E-01 2.1976E-01<_>0 -1 593 -2.2719E-029.7776E-01 -1.8654E-01<_>0 -1 594 1.2705E-02-1.0547E-01 3.7404E-01<_>0 -1 595 -1.3683E-026.1064E-01 -2.6881E-01<_>115-3.7161E+00<_>0 -1 596 3.1358E-02-1.0184E+00 5.7529E-01<_>0 -1 597 9.3050E-02-4.1298E-01 1.0091E+00<_>0 -1 598 2.5950E-02-5.8588E-01 5.6606E-01<_>0 -1 599 1.6472E-02-9.2857E-01 3.0924E-01<_>0 -1 600 -1.8780E-031.1951E-01 -1.1180E+00<_>0 -1 601 -9.0130E-03-5.7850E-01 3.3154E-01<_>0 -1 602 2.2548E-02-3.8325E-01 5.2462E-01<_>0 -1 603 -3.7780E-021.1791E+00 -3.4167E-02<_>0 -1 604 -5.3800E-03-8.6266E-01 1.1868E-01<_>0 -1 605 -2.3893E-02-7.4951E-01 2.1011E-01<_>0 -1 606 -2.6522E-029.2129E-01 -2.8253E-01<_>0 -1 607 1.2280E-022.6663E-01 -7.0014E-01<_>0 -1 608 9.6595E-02-2.8454E-01 7.3169E-01<_>0 -1 609 -2.7415E-02-6.1493E-01 1.5576E-01<_>0 -1 610 -1.5767E-025.7551E-01 -3.4362E-01<_>0 -1 611 -2.1100E-033.2600E-01 -1.3008E-01<_>0 -1 612 1.2007E-028.9323E-02 -9.6026E-01<_>0 -1 613 -1.5422E-023.4449E-01 -4.6712E-01<_>0 -1 614 -4.1580E-032.3696E-01 -5.2563E-01<_>0 -1 615 -2.1186E-02-7.4268E-01 2.1702E-01<_>0 -1 616 -1.7077E-02-9.0472E-01 6.6012E-02<_>0 -1 617 -4.0850E-02-3.4447E-01 2.1504E-01<_>0 -1 618 -8.1930E-03-9.3389E-01 5.0471E-02<_>0 -1 619 -1.9238E-02-5.3204E-01 1.7241E-01<_>0 -1 620 -4.4192E-029.2075E-01 -2.2149E-01<_>0 -1 621 -6.2392E-02-7.1054E-01 1.8324E-01<_>0 -1 622 -1.0080E-03-8.7063E-01 5.5330E-02<_>0 -1 623 2.3870E-02-2.2854E-01 5.2416E-01<_>0 -1 624 2.1391E-02-3.0326E-01 5.5861E-01<_>0 -1 625 2.0255E-022.6902E-01 -7.0262E-01<_>0 -1 626 -2.8772E-02-1.1835E+00 4.6512E-02<_>0 -1 627 3.4200E-03-5.4652E-01 2.5962E-01<_>0 -1 628 5.6983E-02-2.6983E-01 5.8171E-01<_>0 -1 629 -9.3892E-02-9.1046E-01 1.9678E-01<_>0 -1 630 1.7700E-02-4.4003E-01 2.1350E-01<_>0 -1 631 2.2844E-012.3605E-02 7.7172E-01<_>0 -1 632 -1.8288E-017.9229E-01 -2.4645E-01<_>0 -1 633 -6.9892E-028.0268E-01 -3.6072E-02<_>0 -1 634 1.5297E-02-2.0072E-01 1.1031E+00<_>0 -1 635 6.7500E-03-4.5968E-02 7.2095E-01<_>0 -1 636 -1.5983E-02-9.0357E-01 4.4988E-02<_>0 -1 637 1.3088E-023.5297E-01 -3.7711E-01<_>0 -1 638 1.3061E-02-1.9584E-01 1.1199E+00<_>0 -1 639 -3.9907E-02-1.3998E+00 1.9145E-01<_>0 -1 640 1.5027E-022.3600E-03 -1.1611E+00<_>0 -1 641 -2.0518E-02-4.8908E-01 1.6743E-01<_>0 -1 642 -2.2359E-02-1.2203E+00 -1.1976E-02<_>0 -1 643 -7.9150E-033.7228E-01 -8.5063E-02<_>0 -1 644 1.5258E-02-2.9413E-01 5.9406E-01<_>0 -1 645 -3.1666E-02-1.4396E+00 1.3579E-01<_>0 -1 646 -3.0774E-02-2.2545E+00 -3.3971E-02<_>0 -1 647 -1.5483E-023.7701E-01 1.5848E-02<_>0 -1 648 3.5167E-02-2.9446E-01 5.3159E-01<_>0 -1 649 -1.7906E-02-9.9788E-01 1.6236E-01<_>0 -1 650 -3.1800E-034.7657E-02 -7.5250E-01<_>0 -1 651 1.5720E-021.4874E-01 -6.5375E-01<_>0 -1 652 2.9864E-02-1.4952E-02 -1.2275E+00<_>0 -1 653 2.9900E-03-1.4264E-01 4.3273E-01<_>0 -1 654 8.4750E-02-1.9281E-02 -1.1946E+00<_>0 -1 655 -5.8725E-02-1.7328E+00 1.4375E-01<_>0 -1 656 4.4756E-02-2.4141E-01 5.4020E-01<_>0 -1 657 4.0369E-025.7680E-03 5.6578E-01<_>0 -1 658 3.7736E-023.8181E-02 -7.9370E-01<_>0 -1 659 6.0753E-027.6453E-02 1.4813E+00<_>0 -1 660 -1.9832E-02-1.6972E+00 -2.7370E-02<_>0 -1 661 -1.6593E-016.2976E-01 3.1763E-02<_>0 -1 662 6.9015E-02-3.3463E-01 3.0077E-01<_>0 -1 663 1.1358E-022.2741E-01 -3.8225E-01<_>0 -1 664 1.7000E-031.9224E-01 -5.2735E-01<_>0 -1 665 7.9769E-029.1492E-02 2.1049E+00<_>0 -1 666 -5.7144E-02-1.7452E+00 -4.0910E-02<_>0 -1 667 7.3830E-03-2.4215E-01 3.5578E-01<_>0 -1 668 -1.8041E-021.1780E+00 -1.7677E-01<_>0 -1 669 9.4503E-021.3936E-01 -1.2994E+00<_>0 -1 670 5.4210E-03-5.4609E-01 1.3916E-01<_>0 -1 671 7.0290E-03-2.1597E-01 3.9258E-01<_>0 -1 672 3.4516E-026.3189E-02 -7.2108E-01<_>0 -1 673 -5.1925E-026.8668E-01 6.3273E-02<_>0 -1 674 -6.9162E-021.7412E+00 -1.6619E-01<_>0 -1 675 -5.5230E-033.0695E-01 -1.6663E-01<_>0 -1 676 6.8600E-02-2.1405E-01 7.3185E-01<_>0 -1 677 -6.7039E-02-7.9361E-01 2.0526E-01<_>0 -1 678 -2.1005E-023.7344E-01 -2.9619E-01<_>0 -1 679 2.0279E-02-1.5200E-02 4.0555E-01<_>0 -1 680 -4.7108E-021.2117E+00 -1.7464E-01<_>0 -1 681 1.8768E-01-2.2909E-02 6.9646E-01<_>0 -1 682 -4.3229E-02-1.0602E+00 -5.5600E-04<_>0 -1 683 2.0004E-02-3.2751E-02 5.3805E-01<_>0 -1 684 8.0880E-033.7548E-02 -7.4769E-01<_>0 -1 685 2.7101E-02-8.1790E-02 3.3387E-01<_>0 -1 686 -9.1746E-02-1.9214E+00 -3.8953E-02<_>0 -1 687 -1.2455E-024.8361E-01 1.8168E-02<_>0 -1 688 1.4649E-02-1.9907E-01 7.2815E-01<_>0 -1 689 2.9102E-021.9871E-01 -4.9217E-01<_>0 -1 690 8.7800E-03-1.9500E-01 7.7317E-01<_>0 -1 691 -5.4740E-021.8087E+00 6.8323E-02<_>0 -1 692 -1.4798E-027.8065E-01 -1.8710E-01<_>0 -1 693 2.5013E-021.5285E-01 -1.6021E+00<_>0 -1 694 4.6548E-02-1.6738E-01 1.1902E+00<_>0 -1 695 1.7624E-02-1.0285E-01 3.9176E-01<_>0 -1 696 1.6320E-01-3.5624E-02 -1.6098E+00<_>0 -1 697 1.3138E-02-5.6359E-02 5.4159E-01<_>0 -1 698 -1.5665E-022.8063E-01 -3.1709E-01<_>0 -1 699 8.0554E-021.2640E-01 -1.0298E+00<_>0 -1 700 3.5364E-022.0753E-02 -7.9106E-01<_>0 -1 701 3.2987E-021.9057E-01 -8.3840E-01<_>0 -1 702 1.2195E-027.3729E-02 -6.2781E-01<_>0 -1 703 4.3066E-024.7385E-02 1.5713E+00<_>0 -1 704 3.0327E-02-2.7315E-01 3.8572E-01<_>0 -1 705 3.5493E-025.4594E-02 5.2583E-01<_>0 -1 706 -1.4597E-023.8153E-01 -2.8332E-01<_>0 -1 707 1.2607E-021.5455E-01 -3.0501E-01<_>0 -1 708 1.0172E-022.3637E-02 -8.7218E-01<_>0 -1 709 2.8843E-021.6091E-01 -2.0278E-01<_>0 -1 710 5.5100E-04-6.1545E-01 8.0936E-02<_>127-3.5645E+00<_>0 -1 711 4.8344E-02-8.4905E-01 5.6974E-01<_>0 -1 712 3.2460E-02-8.1417E-01 4.4782E-01<_>0 -1 713 3.3340E-02-3.6424E-01 6.7937E-01<_>0 -1 714 6.4020E-03-1.1885E+00 1.9239E-01<_>0 -1 715 -5.6890E-033.3085E-01 -7.1334E-01<_>0 -1 716 1.2698E-02-5.0991E-01 1.1376E-01<_>0 -1 717 6.0550E-03-1.0471E+00 2.0223E-01<_>0 -1 718 2.6420E-03-5.0559E-01 3.6441E-01<_>0 -1 719 -1.6926E-02-9.9542E-01 1.2602E-01<_>0 -1 720 2.8236E-02-9.4138E-02 5.7780E-01<_>0 -1 721 1.0429E-022.3273E-01 -5.2570E-01<_>0 -1 722 9.8860E-03-1.0316E-01 4.7658E-01<_>0 -1 723 2.6015E-02-1.0920E-03 -1.5582E+00<_>0 -1 724 -2.5538E-02-6.5451E-01 1.8843E-01<_>0 -1 725 -3.5310E-032.8141E-01 -4.4575E-01<_>0 -1 726 9.2450E-031.5612E-01 -2.1371E-01<_>0 -1 727 2.1031E-02-2.9170E-01 5.2234E-01<_>0 -1 728 -5.1063E-021.3661E+00 3.0466E-02<_>0 -1 729 -6.2330E-021.2207E+00 -2.2434E-01<_>0 -1 730 -3.2963E-02-8.2017E-01 1.4532E-01<_>0 -1 731 -3.7418E-02-1.2218E+00 1.9449E-02<_>0 -1 732 1.2403E-011.2082E-01 -9.8729E-01<_>0 -1 733 -8.9230E-03-1.1688E+00 2.1105E-02<_>0 -1 734 -5.9880E-02-1.0689E+00 1.9860E-01<_>0 -1 735 6.2620E-03-3.6230E-01 3.8001E-01<_>0 -1 736 -1.7673E-024.9094E-01 -1.4607E-01<_>0 -1 737 1.7579E-025.8728E-01 -2.7774E-01<_>0 -1 738 5.1560E-03-7.5195E-02 6.0193E-01<_>0 -1 739 -1.0600E-022.7637E-01 -3.7794E-01<_>0 -1 740 2.0884E-01-5.3600E-03 1.0318E+00<_>0 -1 741 -2.6413E-028.2336E-01 -2.2481E-01<_>0 -1 742 5.8892E-021.3098E-01 -1.1854E+00<_>0 -1 743 -1.1579E-02-9.0668E-01 4.4127E-02<_>0 -1 744 4.5988E-021.0144E-02 1.0741E+00<_>0 -1 745 -2.2838E-021.7792E+00 -1.7315E-01<_>0 -1 746 -8.1710E-035.7386E-01 -7.4106E-02<_>0 -1 747 3.5360E-03-3.2073E-01 4.0183E-01<_>0 -1 748 4.9445E-021.9288E-01 -1.2167E+00<_>0 -1 749 3.5140E-036.9568E-02 -7.1324E-01<_>0 -1 750 -3.0996E-02-3.8862E-01 1.8099E-01<_>0 -1 751 8.6453E-02-2.5793E-02 -1.5453E+00<_>0 -1 752 -1.3653E-01-1.9199E+00 1.6613E-01<_>0 -1 753 -5.7690E-03-1.2823E+00 -1.5908E-02<_>0 -1 754 -1.7900E-02-4.0410E-01 2.3592E-01<_>0 -1 755 -1.9970E-02-7.2892E-01 5.6235E-02<_>0 -1 756 -5.7493E-025.7831E-01 -1.5796E-02<_>0 -1 757 -8.3056E-029.1512E-01 -2.1121E-01<_>0 -1 758 -5.3771E-02-5.1931E-01 1.8576E-01<_>0 -1 759 -8.3670E-032.4110E-01 -3.9649E-01<_>0 -1 760 5.5407E-021.6771E-01 -2.5665E+00<_>0 -1 761 -6.7181E-02-1.3659E+00 -1.4232E-02<_>0 -1 762 -2.3900E-02-1.7085E+00 1.6508E-01<_>0 -1 763 5.5950E-03-3.1374E-01 3.2838E-01<_>0 -1 764 2.1295E-021.4953E-01 -4.8580E-01<_>0 -1 765 -2.4613E-027.4346E-01 -2.2305E-01<_>0 -1 766 -1.9626E-02-4.0918E-01 1.8893E-01<_>0 -1 767 -5.3266E-028.1382E-01 -2.0854E-01<_>0 -1 768 7.1290E-033.2996E-01 -5.9937E-01<_>0 -1 769 -2.2487E-02-1.2552E+00 -2.0413E-02<_>0 -1 770 -8.2311E-021.3821E+00 5.9309E-02<_>0 -1 771 1.3097E-01-3.5844E-02 -1.5396E+00<_>0 -1 772 1.4293E-02-1.8475E-01 3.7455E-01<_>0 -1 773 6.3480E-03-4.4901E-01 1.3877E-01<_>0 -1 774 -4.6055E-026.7833E-01 -1.7072E-02<_>0 -1 775 5.7694E-02-1.1956E-02 -1.2261E+00<_>0 -1 776 -6.0610E-033.3959E-01 6.2800E-04<_>0 -1 777 -5.2163E-02-1.0621E+00 -1.3780E-02<_>0 -1 778 4.6573E-021.4539E-01 -1.2385E+00<_>0 -1 779 7.5310E-03-2.4468E-01 5.1377E-01<_>0 -1 780 2.1615E-021.3073E-01 -7.0997E-01<_>0 -1 781 -1.7864E-02-1.0475E+00 4.9600E-04<_>0 -1 782 -3.7195E-02-1.5127E+00 1.4801E-01<_>0 -1 783 -3.1100E-041.3972E-01 -4.6867E-01<_>0 -1 784 2.5043E-022.8632E-01 -4.1795E-01<_>0 -1 785 9.3450E-03-2.7336E-01 4.3445E-01<_>0 -1 786 3.2364E-021.8439E-01 -9.5019E-01<_>0 -1 787 -6.2300E-033.2582E-01 -3.0816E-01<_>0 -1 788 5.1489E-021.1416E-01 -1.9795E+00<_>0 -1 789 -2.6449E-02-1.1067E+00 -8.5520E-03<_>0 -1 790 -1.5420E-028.0139E-01 -3.2035E-02<_>0 -1 791 1.9457E-02-2.6449E-01 3.8754E-01<_>0 -1 792 3.3621E-021.6052E-02 5.8841E-01<_>0 -1 793 2.8906E-021.5216E-02 -9.4724E-01<_>0 -1 794 2.0300E-04-3.0766E-01 2.1236E-01<_>0 -1 795 -4.9142E-02-1.6059E+00 -3.1095E-02<_>0 -1 796 7.6426E-027.4759E-02 1.1639E+00<_>0 -1 797 2.3898E-02-6.4320E-03 -1.1151E+00<_>0 -1 798 3.8970E-03-2.4106E-01 2.0859E-01<_>0 -1 799 -8.9445E-021.9158E+00 -1.5721E-01<_>0 -1 800 -1.5009E-02-2.5174E-01 1.8180E-01<_>0 -1 801 -1.1146E-02-6.9349E-01 4.4928E-02<_>0 -1 802 9.4579E-021.8102E-01 -7.4979E-01<_>0 -1 803 5.5039E-01-3.0974E-02 -1.6746E+00<_>0 -1 804 4.1381E-026.3910E-02 7.6561E-01<_>0 -1 805 2.4772E-021.1380E-02 -8.8559E-01<_>0 -1 806 5.0999E-021.4890E-01 -2.4634E+00<_>0 -1 807 -1.6894E-023.8871E-01 -2.9880E-01<_>0 -1 808 -1.2162E-01-1.5543E+00 1.6301E-01<_>0 -1 809 -3.6050E-032.1843E-01 -3.7312E-01<_>0 -1 810 1.1575E-01-4.7061E-02 5.9404E-01<_>0 -1 811 3.6904E-02-2.5509E-01 5.5397E-01<_>0 -1 812 1.1484E-02-1.8129E-01 4.0683E-01<_>0 -1 813 -2.0234E-025.4311E-01 -2.3822E-01<_>0 -1 814 -2.8765E-02-6.9172E-01 1.5943E-01<_>0 -1 815 -5.8320E-032.9448E-01 -3.4006E-01<_>0 -1 816 -5.5469E-029.2201E-01 9.4093E-02<_>0 -1 817 -1.4801E-02-7.9540E-01 3.1522E-02<_>0 -1 818 -7.0940E-033.3096E-01 -5.0887E-02<_>0 -1 819 -4.5124E-02-1.3720E+00 -2.1409E-02<_>0 -1 820 6.4377E-026.3902E-02 9.1478E-01<_>0 -1 821 -1.4727E-023.6051E-01 -2.8615E-01<_>0 -1 822 4.5007E-02-1.5620E-01 5.3160E-01<_>0 -1 823 -1.1330E-031.3423E-01 -4.4359E-01<_>0 -1 824 4.9451E-021.0572E-01 -2.5589E+00<_>0 -1 825 2.9103E-02-1.0088E-02 -1.1074E+00<_>0 -1 826 3.4786E-02-2.7720E-03 5.6701E-01<_>0 -1 827 -6.1310E-03-4.6889E-01 1.2636E-01<_>0 -1 828 1.5525E-02-8.4280E-03 8.7469E-01<_>0 -1 829 2.9250E-03-3.4434E-01 2.0852E-01<_>0 -1 830 -5.3571E-021.4983E+00 5.7328E-02<_>0 -1 831 -1.9218E-02-9.9234E-01 -9.3920E-03<_>0 -1 832 -5.5283E-02-5.7682E-01 1.6861E-01<_>0 -1 833 5.6336E-02-3.3775E-02 -1.3890E+00<_>0 -1 834 -2.3824E-024.0182E-01 1.8360E-03<_>0 -1 835 1.7810E-031.8146E-01 -4.1743E-01<_>0 -1 836 -3.7689E-025.4683E-01 1.8220E-02<_>0 -1 837 -2.4145E-026.8352E-01 -1.9650E-01<_>135-3.7026E+00<_>0 -1 838 2.7445E-02-8.9984E-01 5.1876E-01<_>0 -1 839 1.1554E-01-5.6524E-01 7.0551E-01<_>0 -1 840 -2.2297E-023.6080E-01 -6.6865E-01<_>0 -1 841 1.3325E-02-5.5573E-01 3.5790E-01<_>0 -1 842 -3.8060E-03-1.0713E+00 1.8850E-01<_>0 -1 843 -2.6820E-03-7.1584E-01 2.6344E-01<_>0 -1 844 3.3820E-03-4.6931E-01 2.6658E-01<_>0 -1 845 3.7643E-022.1099E-01 -1.0804E+00<_>0 -1 846 -1.3862E-026.6912E-01 -2.7943E-01<_>0 -1 847 -2.7350E-03-9.5332E-01 2.4051E-01<_>0 -1 848 -3.8337E-028.1433E-01 -2.4919E-01<_>0 -1 849 -3.4698E-021.2330E+00 6.8600E-03<_>0 -1 850 2.3361E-02-3.0795E-01 7.0714E-01<_>0 -1 851 3.5058E-022.1206E-01 -1.4400E+00<_>0 -1 852 -1.3257E-02-9.0261E-01 4.8610E-02<_>0 -1 853 1.2740E-022.2655E-01 -4.4644E-01<_>0 -1 854 3.6400E-03-3.9818E-01 3.4665E-01<_>0 -1 855 1.0065E-011.8384E-01 -1.3411E+00<_>0 -1 856 0.1.5536E-01 -5.1582E-01<_>0 -1 857 1.1709E-022.1651E-01 -7.2705E-01<_>0 -1 858 -3.5965E-02-1.4790E+00 -2.4317E-02<_>0 -1 859 -2.1236E-02-1.6844E-01 1.9527E-01<_>0 -1 860 1.4874E-023.7336E-02 -8.7557E-01<_>0 -1 861 -5.1410E-033.3467E-01 -2.4110E-01<_>0 -1 862 2.3450E-025.5320E-03 -1.2510E+00<_>0 -1 863 -2.5062E-024.5212E-01 -8.4470E-02<_>0 -1 864 -7.7400E-041.5250E-01 -4.8487E-01<_>0 -1 865 -4.0484E-02-1.3025E+00 1.7984E-01<_>0 -1 866 2.8171E-02-2.4411E-01 6.2271E-01<_>0 -1 867 4.5693E-022.8122E-02 9.2394E-01<_>0 -1 868 3.9707E-02-2.2333E-01 7.7674E-01<_>0 -1 869 5.0517E-022.0320E-01 -1.0896E+00<_>0 -1 870 -1.7267E-026.8598E-01 -2.3304E-01<_>0 -1 871 8.0186E-02-1.0292E-02 6.1881E-01<_>0 -1 872 9.7676E-02-2.0070E-01 1.0088E+00<_>0 -1 873 -1.5572E-024.7615E-01 4.5624E-02<_>0 -1 874 -1.5305E-02-1.1077E+00 4.5240E-03<_>0 -1 875 -1.6485E-021.0153E+00 1.6328E-02<_>0 -1 876 -2.6142E-024.1723E-01 -2.8646E-01<_>0 -1 877 8.8680E-032.1405E-01 -1.6773E-01<_>0 -1 878 -2.6887E-02-1.1564E+00 -1.0324E-02<_>0 -1 879 7.7790E-033.5359E-01 -2.9611E-01<_>0 -1 880 -1.5974E-02-1.5374E+00 -2.9958E-02<_>0 -1 881 2.0867E-022.0244E-01 -7.1270E-01<_>0 -1 882 8.5482E-02-2.5933E-02 -1.5157E+00<_>0 -1 883 2.3873E-021.6803E-01 -3.8806E-01<_>0 -1 884 -3.9105E-02-1.1958E+00 -2.0361E-02<_>0 -1 885 -7.7947E-02-1.0899E+00 1.4530E-01<_>0 -1 886 -1.6876E-022.8050E-01 -4.1336E-01<_>0 -1 887 1.1876E-01-4.3491E-02 4.1264E-01<_>0 -1 888 1.5624E-01-2.6430E-01 5.5128E-01<_>0 -1 889 -4.5908E-026.0189E-01 1.8921E-02<_>0 -1 890 -1.0310E-023.8153E-01 -2.9508E-01<_>0 -1 891 9.5769E-021.3247E-01 -4.6267E-01<_>0 -1 892 1.3687E-021.1739E-01 -5.1664E-01<_>0 -1 893 2.3990E-03-3.4008E-01 2.0954E-01<_>0 -1 894 3.3265E-02-1.7053E-01 1.4367E+00<_>0 -1 895 -3.3206E-026.1296E-01 -4.1550E-02<_>0 -1 896 2.7980E-03-4.8554E-01 1.3373E-01<_>0 -1 897 -6.5792E-02-4.0258E+00 1.0877E-01<_>0 -1 898 2.1430E-03-3.9180E-01 2.2427E-01<_>0 -1 899 2.2364E-02-8.6430E-02 3.7785E-01<_>0 -1 900 -5.7410E-021.1454E+00 -1.9737E-01<_>0 -1 901 6.6550E-03-2.1105E-02 5.8453E-01<_>0 -1 902 1.2327E-023.7817E-02 -6.6987E-01<_>0 -1 903 -8.1870E-035.6366E-01 -7.6878E-02<_>0 -1 904 3.6681E-02-1.7343E-01 1.1670E+00<_>0 -1 905 -4.0220E-011.2641E+00 4.3399E-02<_>0 -1 906 -2.2126E-026.6978E-01 -2.1605E-01<_>0 -1 907 -1.3157E-02-4.1199E-01 2.0215E-01<_>0 -1 908 -1.2860E-02-9.1583E-01 3.9233E-02<_>0 -1 909 2.1628E-023.8720E-03 3.5668E-01<_>0 -1 910 1.1896E-02-3.7304E-01 1.9235E-01<_>0 -1 911 -1.9549E-02-4.2375E-01 2.4430E-01<_>0 -1 912 6.4445E-02-1.6559E-01 1.2697E+00<_>0 -1 913 1.0898E-011.4894E-01 -2.1535E+00<_>0 -1 914 -3.4078E-021.3779E+00 -1.6198E-01<_>0 -1 915 -3.7490E-03-3.3829E-01 2.1153E-01<_>0 -1 916 -1.0972E-027.6518E-01 -1.9693E-01<_>0 -1 917 -1.1485E-02-6.9271E-01 2.1657E-01<_>0 -1 918 2.5984E-02-1.1984E-02 -9.9697E-01<_>0 -1 919 4.2160E-03-1.0206E-01 4.8884E-01<_>0 -1 920 -4.7697E-021.0666E+00 -1.7576E-01<_>0 -1 921 4.0300E-041.8525E-01 -7.4790E-01<_>0 -1 922 1.1540E-01-2.2020E-01 5.4510E-01<_>0 -1 923 1.6021E-022.5488E-01 -5.0740E-01<_>0 -1 924 5.6632E-02-1.1256E-02 -9.5968E-01<_>0 -1 925 -1.0726E-02-2.8545E-01 1.6995E-01<_>0 -1 926 1.2420E-01-3.6140E-02 -1.3133E+00<_>0 -1 927 -5.3800E-033.3093E-01 1.3308E-02<_>0 -1 928 1.1908E-02-3.4830E-01 2.4042E-01<_>0 -1 929 -4.3008E-02-1.4390E+00 1.5600E-01<_>0 -1 930 -3.3150E-02-1.1806E+00 -1.2348E-02<_>0 -1 931 -2.1342E-022.2119E+00 6.2737E-02<_>0 -1 932 -1.2219E-02-1.8710E+00 -4.5500E-02<_>0 -1 933 -1.6861E-02-7.6913E-01 1.5330E-01<_>0 -1 934 -2.5000E-03-6.2987E-01 5.1600E-02<_>0 -1 935 -4.5038E-028.5429E-01 6.2600E-03<_>0 -1 936 3.9058E-02-3.2459E-02 -1.3326E+00<_>0 -1 937 6.6720E-03-1.9424E-01 3.7329E-01<_>0 -1 938 -1.6361E-022.0606E+00 -1.5043E-01<_>0 -1 939 6.1720E-03-1.1611E-01 2.5455E-01<_>0 -1 940 4.5722E-02-1.6340E-02 -1.0449E+00<_>0 -1 941 4.1210E-03-4.1998E-02 3.9681E-01<_>0 -1 942 -1.7800E-04-6.6423E-01 3.3443E-02<_>0 -1 943 7.1110E-03-5.8232E-02 3.7857E-01<_>0 -1 944 -4.9864E-026.1019E-01 -2.1006E-01<_>0 -1 945 -2.5012E-02-5.7100E-01 1.7848E-01<_>0 -1 946 3.0940E-025.6363E-02 -6.4731E-01<_>0 -1 947 4.6271E-021.7482E-01 -9.8909E-01<_>0 -1 948 -3.1870E-03-6.6805E-01 3.2267E-02<_>0 -1 949 -2.4352E-022.9445E-01 -1.3600E-03<_>0 -1 950 1.1974E-02-2.8345E-01 4.7171E-01<_>0 -1 951 1.3070E-02-1.0835E-01 5.7193E-01<_>0 -1 952 5.9163E-02-5.0939E-02 -1.9060E+00<_>0 -1 953 -4.1095E-024.5105E-01 -9.7600E-03<_>0 -1 954 -8.3989E-02-2.0349E+00 -5.1019E-02<_>0 -1 955 4.4619E-021.7041E-01 -1.2279E+00<_>0 -1 956 2.4419E-02-2.1797E-02 -1.0823E+00<_>0 -1 957 -4.3870E-033.0467E-01 -3.7067E-01<_>0 -1 958 2.4608E-02-3.1170E-01 2.3657E-01<_>0 -1 959 -8.5182E-02-1.7982E+00 1.5254E-01<_>0 -1 960 2.1845E-02-5.1888E-02 -1.9017E+00<_>0 -1 961 -1.6829E-022.1026E-01 2.1657E-02<_>0 -1 962 3.2548E-02-2.0293E-01 6.0944E-01<_>0 -1 963 2.4710E-03-9.5371E-01 1.8568E-01<_>0 -1 964 5.5416E-02-1.4405E-01 2.1506E+00<_>0 -1 965 -1.0635E-01-1.0912E+00 1.3228E-01<_>0 -1 966 -7.9890E-031.0253E-01 -5.1745E-01<_>0 -1 967 7.5568E-025.8965E-02 1.2354E+00<_>0 -1 968 -9.2806E-02-1.3432E+00 -3.4463E-02<_>0 -1 969 4.9432E-024.9602E-02 1.6055E+00<_>0 -1 970 -1.1773E-02-1.0261E+00 -4.1560E-03<_>0 -1 971 8.5886E-028.4643E-02 9.5221E-01<_>0 -1 972 8.1031E-02-1.4687E-01 1.9360E+00<_>136-3.4266E+00<_>0 -1 973 -3.3841E-026.5890E-01 -6.9755E-01<_>0 -1 974 1.5410E-02-9.0728E-01 3.0479E-01<_>0 -1 975 5.4906E-02-4.9775E-01 5.7133E-01<_>0 -1 976 2.1390E-02-4.2565E-01 5.8097E-01<_>0 -1 977 7.8850E-03-4.7906E-01 4.3016E-01<_>0 -1 978 -3.7545E-025.0862E-01 -1.9986E-01<_>0 -1 979 1.5926E-01-2.3264E-01 1.0993E+00<_>0 -1 980 -6.8940E-024.0569E-01 5.6855E-02<_>0 -1 981 -3.3695E-024.5133E-01 -3.3333E-01<_>0 -1 982 -6.3315E-02-8.5016E-01 2.2342E-01<_>0 -1 983 7.3700E-03-9.3082E-01 5.9217E-02<_>0 -1 984 -9.5970E-03-1.2795E+00 1.8447E-01<_>0 -1 985 -1.3068E-015.8427E-01 -2.6007E-01<_>0 -1 986 5.7403E-02-5.3789E-02 7.1176E-01<_>0 -1 987 -7.2340E-03-8.6962E-01 7.5215E-02<_>0 -1 988 3.1099E-02-7.5007E-02 9.0782E-01<_>0 -1 989 3.5854E-02-2.4795E-01 7.2272E-01<_>0 -1 990 -3.1535E-02-1.1238E+00 2.0988E-01<_>0 -1 991 -1.9437E-02-1.4499E+00 -1.5100E-02<_>0 -1 992 -7.2420E-035.3865E-01 -1.1375E-01<_>0 -1 993 8.1640E-036.6889E-02 -7.6873E-01<_>0 -1 994 -4.3653E-021.1414E+00 4.0217E-02<_>0 -1 995 2.6570E-02-2.4719E-01 5.9295E-01<_>0 -1 996 3.2217E-02-4.0025E-02 3.2688E-01<_>0 -1 997 -7.2236E-025.8729E-01 -2.5396E-01<_>0 -1 998 3.1425E-021.5315E-01 -5.6042E-01<_>0 -1 999 -4.7700E-041.6959E-01 -5.2627E-01<_>0 -1 1000 2.7190E-03-1.4945E-01 2.9659E-01<_>0 -1 1001 3.2875E-02-3.9944E-01 2.5157E-01<_>0 -1 1002 -1.4553E-022.7973E-01 -4.7204E-01<_>0 -1 1003 3.8018E-02-2.9200E-03 -1.1300E+00<_>0 -1 1004 2.8660E-034.1112E-01 -2.6221E-01<_>0 -1 1005 -4.1607E-02-1.4294E+00 -1.9133E-02<_>0 -1 1006 -2.4803E-02-2.5014E-01 1.5979E-01<_>0 -1 1007 1.0098E-024.3739E-02 -6.9986E-01<_>0 -1 1008 -2.0947E-02-9.4138E-01 2.3204E-01<_>0 -1 1009 2.2458E-02-2.7186E-01 4.5319E-01<_>0 -1 1010 -3.7111E-02-1.0315E+00 1.4422E-01<_>0 -1 1011 -1.0648E-026.3107E-01 -2.5521E-01<_>0 -1 1012 5.5423E-021.6207E-01 -1.7723E+00<_>0 -1 1013 2.1602E-02-2.5016E-01 5.4120E-01<_>0 -1 1014 8.7000E-05-2.9009E-01 3.3508E-01<_>0 -1 1015 1.4406E-02-7.8840E-03 -1.1677E+00<_>0 -1 1016 1.0777E-011.1292E-01 -2.4940E+00<_>0 -1 1017 3.5944E-02-1.9481E-01 9.5758E-01<_>0 -1 1018 -3.9510E-033.0928E-01 -2.5530E-01<_>0 -1 1019 2.0942E-02-7.6320E-03 -1.0086E+00<_>0 -1 1020 -2.9878E-02-4.6028E-01 1.9507E-01<_>0 -1 1021 2.5972E-02-1.2188E-02 -1.0036E+00<_>0 -1 1022 1.0603E-02-7.5969E-02 4.1670E-01<_>0 -1 1023 8.5820E-03-2.6649E-01 3.9112E-01<_>0 -1 1024 2.1271E-021.8274E-01 -3.6052E-01<_>0 -1 1025 7.4518E-02-1.8938E-01 9.2658E-01<_>0 -1 1026 4.6570E-03-1.4506E-01 3.3295E-01<_>0 -1 1027 1.7120E-03-5.2464E-01 8.9880E-02<_>0 -1 1028 9.8500E-04-3.8382E-01 2.4393E-01<_>0 -1 1029 2.8234E-02-5.7880E-03 -1.2617E+00<_>0 -1 1030 -3.2678E-02-5.7953E-01 1.6955E-01<_>0 -1 1031 2.2536E-022.2281E-02 -8.7870E-01<_>0 -1 1032 -2.1658E-02-6.5109E-01 1.2967E-01<_>0 -1 1033 7.6800E-03-3.3965E-01 2.2013E-01<_>0 -1 1034 1.4592E-021.5077E-01 -5.0452E-01<_>0 -1 1035 2.7868E-02-2.5045E-01 4.5742E-01<_>0 -1 1036 5.6940E-03-1.0949E-01 5.5758E-01<_>0 -1 1037 -1.0003E-02-9.7366E-01 1.8468E-02<_>0 -1 1038 -4.0720E-033.8222E-01 -1.6921E-01<_>0 -1 1039 -2.2594E-02-1.0391E+00 5.1840E-03<_>0 -1 1040 -3.9580E-02-5.5109E+00 1.1164E-01<_>0 -1 1041 -1.7538E-029.5486E-01 -1.8585E-01<_>0 -1 1042 9.0300E-031.0436E-02 8.2115E-01<_>0 -1 1043 -7.9540E-032.2633E-01 -3.4568E-01<_>0 -1 1044 2.7091E-021.6430E-01 -1.3926E+00<_>0 -1 1045 -2.0626E-02-8.6366E-01 2.3880E-03<_>0 -1 1046 -7.1990E-02-2.8193E+00 1.1570E-01<_>0 -1 1047 -2.6965E-02-1.2946E+00 -2.4661E-02<_>0 -1 1048 -4.7378E-02-8.1306E-01 1.1831E-01<_>0 -1 1049 -1.0896E-016.5938E-01 -2.0844E-01<_>0 -1 1050 1.3574E-027.4240E-03 5.3152E-01<_>0 -1 1051 -6.6920E-033.0656E-01 -3.1084E-01<_>0 -1 1052 -3.9070E-032.5576E-01 -5.2932E-02<_>0 -1 1053 -3.7613E-02-1.4350E+00 -1.5448E-02<_>0 -1 1054 8.6330E-03-1.6884E-01 4.2125E-01<_>0 -1 1055 -3.2097E-02-6.4979E-01 4.1110E-02<_>0 -1 1056 5.8496E-02-5.2964E-02 6.3368E-01<_>0 -1 1057 -4.0902E-02-9.2101E-01 9.0640E-03<_>0 -1 1058 -1.9925E-025.3760E-01 -6.2997E-02<_>0 -1 1059 -4.6020E-03-5.4334E-01 8.4105E-02<_>0 -1 1060 1.6825E-021.5564E-01 -4.0171E-01<_>0 -1 1061 9.4790E-03-2.4245E-01 5.1509E-01<_>0 -1 1062 -1.9535E-02-5.1118E-01 1.3832E-01<_>0 -1 1063 1.0746E-02-2.1855E-01 6.2829E-01<_>0 -1 1064 3.7927E-021.1640E-01 -2.7302E+00<_>0 -1 1065 1.6391E-02-1.4636E-02 -1.0797E+00<_>0 -1 1066 -1.9785E-021.2166E+00 3.3275E-02<_>0 -1 1067 1.1067E-02-2.5388E-01 4.4039E-01<_>0 -1 1068 5.2480E-032.2497E-01 -2.4216E-01<_>0 -1 1069 -1.1142E-022.5018E-01 -3.0812E-01<_>0 -1 1070 -1.0667E-02-3.2729E-01 2.6168E-01<_>0 -1 1071 1.0545E-01-5.5750E-02 -1.9606E+00<_>0 -1 1072 5.4828E-02-1.9520E-03 7.3866E-01<_>0 -1 1073 1.7761E-02-3.0647E-01 2.6347E-01<_>0 -1 1074 -3.1186E-02-2.4601E-01 1.7082E-01<_>0 -1 1075 -5.7296E-024.7034E-01 -2.6048E-01<_>0 -1 1076 -1.1312E-023.8629E-01 -2.8817E-01<_>0 -1 1077 3.0592E-02-4.8826E-02 -1.7639E+00<_>0 -1 1078 1.8490E-032.1100E-01 -2.5941E-02<_>0 -1 1079 1.1419E-02-1.6830E-01 1.0279E+00<_>0 -1 1080 8.1403E-021.1532E-01 -1.2482E+00<_>0 -1 1081 5.3496E-02-4.6304E-02 -1.7166E+00<_>0 -1 1082 -2.3948E-02-4.0247E-01 2.0562E-01<_>0 -1 1083 6.7690E-03-3.3152E-01 2.0683E-01<_>0 -1 1084 -3.2344E-02-7.2633E-01 2.0074E-01<_>0 -1 1085 3.7863E-02-1.5631E-01 1.6697E+00<_>0 -1 1086 1.5440E-021.9487E-01 -3.5384E-01<_>0 -1 1087 -4.4376E-028.2094E-01 -1.8194E-01<_>0 -1 1088 -2.3102E-02-4.3044E-01 1.2375E-01<_>0 -1 1089 1.9400E-02-2.9726E-02 -1.1598E+00<_>0 -1 1090 1.0386E-011.1150E-01 -4.6835E+00<_>0 -1 1091 -1.8964E-022.1774E+00 -1.4544E-01<_>0 -1 1092 3.8751E-02-4.9446E-02 3.4018E-01<_>0 -1 1093 2.2767E-02-3.2803E-01 3.0531E-01<_>0 -1 1094 -3.1357E-021.1521E+00 2.7306E-02<_>0 -1 1095 9.6910E-03-3.8800E-01 2.1513E-01<_>0 -1 1096 -4.9285E-02-1.6775E+00 1.5774E-01<_>0 -1 1097 -3.9511E-02-9.7648E-01 -1.0552E-02<_>0 -1 1098 4.7998E-022.0844E-01 -6.8993E-01<_>0 -1 1099 5.1423E-02-1.6665E-01 1.2149E+00<_>0 -1 1100 1.4280E-022.3628E-01 -4.1397E-01<_>0 -1 1101 -9.1612E-02-9.2831E-01 -1.8345E-02<_>0 -1 1102 6.5080E-03-7.3647E-01 1.9497E-01<_>0 -1 1103 3.5723E-021.4198E-01 -4.2089E-01<_>0 -1 1104 5.0638E-021.1644E-02 7.8487E-01<_>0 -1 1105 -1.4614E-02-1.1910E+00 -3.5128E-02<_>0 -1 1106 -3.8663E-022.4315E+00 6.5648E-02<_>0 -1 1107 -4.0347E-027.1755E-01 -1.9108E-01<_>0 -1 1108 2.3902E-021.5646E-01 -7.9295E-01<_>137-3.5125E+00<_>0 -1 1109 8.5640E-03-8.1451E-01 5.8875E-01<_>0 -1 1110 -1.3293E-019.3213E-01 -2.9367E-01<_>0 -1 1111 9.8400E-03-5.6463E-01 4.1648E-01<_>0 -1 1112 5.0890E-03-7.9233E-01 1.6975E-01<_>0 -1 1113 -6.1039E-02-1.4169E+00 2.5021E-02<_>0 -1 1114 -4.6600E-043.7982E-01 -4.1567E-01<_>0 -1 1115 3.3890E-03-4.0769E-01 3.5548E-01<_>0 -1 1116 2.1007E-02-2.4080E-01 8.6113E-01<_>0 -1 1117 7.5560E-03-8.7467E-01 9.8572E-02<_>0 -1 1118 2.4780E-021.5566E-01 -6.9230E-01<_>0 -1 1119 -3.5620E-02-1.1472E+00 3.6360E-02<_>0 -1 1120 1.9810E-021.5516E-01 -6.9520E-01<_>0 -1 1121 1.5020E-024.1990E-02 -9.6623E-01<_>0 -1 1122 -2.3138E-024.3397E-01 2.4160E-03<_>0 -1 1123 -1.8743E-024.3481E-01 -3.2522E-01<_>0 -1 1124 4.5080E-01-9.4574E-02 7.2421E-01<_>0 -1 1125 1.1855E-02-3.8133E-01 3.0098E-01<_>0 -1 1126 -2.4830E-028.9301E-01 -1.0296E-01<_>0 -1 1127 -4.4743E-028.6280E-01 -2.1716E-01<_>0 -1 1128 -1.4600E-026.0069E-01 -1.5906E-01<_>0 -1 1129 -2.4527E-02-1.5873E+00 -2.1817E-02<_>0 -1 1130 2.3024E-021.6853E-01 -3.8107E-01<_>0 -1 1131 -2.4917E-025.0811E-01 -2.7280E-01<_>0 -1 1132 1.0130E-03-4.3139E-01 2.6438E-01<_>0 -1 1133 1.5603E-02-3.1624E-01 5.5716E-01<_>0 -1 1134 -2.6686E-021.0554E+00 2.9074E-02<_>0 -1 1135 1.3940E-03-7.1874E-01 6.5391E-02<_>0 -1 1136 -6.4800E-042.4884E-01 -2.0978E-01<_>0 -1 1137 -3.1888E-02-6.8844E-01 6.3590E-02<_>0 -1 1138 -4.9290E-03-5.9153E-01 2.7944E-01<_>0 -1 1139 3.1168E-024.5224E-02 -8.8639E-01<_>0 -1 1140 -3.3663E-02-6.1590E-01 1.5749E-01<_>0 -1 1141 1.1967E-02-3.0607E-01 4.2293E-01<_>0 -1 1142 -3.4680E-02-1.3735E+00 1.5909E-01<_>0 -1 1143 9.9290E-03-5.5860E-01 1.2119E-01<_>0 -1 1144 5.9575E-024.9720E-03 8.2055E-01<_>0 -1 1145 -6.5428E-021.5651E+00 -1.6817E-01<_>0 -1 1146 -9.2896E-02-1.5795E+00 1.4662E-01<_>0 -1 1147 -4.1184E-02-1.5519E+00 -2.9970E-02<_>0 -1 1148 2.1448E-021.7196E-01 -6.9343E-01<_>0 -1 1149 -2.5570E-02-1.3061E+00 -2.4337E-02<_>0 -1 1150 -4.1201E-02-1.3821E+00 1.4802E-01<_>0 -1 1151 -1.7669E-02-7.0890E-01 3.6524E-02<_>0 -1 1152 9.0060E-03-4.0914E-02 8.0373E-01<_>0 -1 1153 -1.1653E-025.7547E-01 -2.4992E-01<_>0 -1 1154 -7.4780E-03-4.9281E-01 1.9811E-01<_>0 -1 1155 8.5500E-04-4.8858E-01 1.3563E-01<_>0 -1 1156 -3.0538E-02-6.0278E-01 1.8522E-01<_>0 -1 1157 -1.8847E-022.3566E-01 -3.5136E-01<_>0 -1 1158 -8.1130E-03-8.1305E-02 2.1070E-01<_>0 -1 1159 -3.4830E-02-1.2066E+00 -1.4252E-02<_>0 -1 1160 1.9021E-022.3350E-01 -4.5665E-01<_>0 -1 1161 -1.9004E-02-8.1076E-01 1.3140E-02<_>0 -1 1162 -8.9058E-026.1542E-01 3.2983E-02<_>0 -1 1163 6.8620E-03-2.9583E-01 2.7004E-01<_>0 -1 1164 -2.8241E-02-6.1103E-01 1.7357E-01<_>0 -1 1165 -3.2100E-04-5.3323E-01 6.8539E-02<_>0 -1 1166 -1.0829E-01-1.2880E+00 1.1802E-01<_>0 -1 1167 1.5879E-02-1.7073E-01 1.1104E+00<_>0 -1 1168 8.6860E-03-1.0995E-01 4.6011E-01<_>0 -1 1169 -2.5235E-021.0221E+00 -1.8694E-01<_>0 -1 1170 -1.3509E-02-7.8317E-01 1.4203E-01<_>0 -1 1171 -7.7150E-03-8.8061E-01 1.1060E-02<_>0 -1 1172 7.1580E-021.1369E-01 -1.1033E+00<_>0 -1 1173 -1.3554E-02-8.1097E-01 3.4080E-03<_>0 -1 1174 2.9450E-03-7.2880E-02 3.4998E-01<_>0 -1 1175 -5.0833E-02-1.2869E+00 -2.8842E-02<_>0 -1 1176 -8.7990E-034.7614E-01 -1.4690E-01<_>0 -1 1177 2.1424E-01-5.9702E-02 -2.4802E+00<_>0 -1 1178 1.3963E-021.7420E-01 -4.3911E-01<_>0 -1 1179 4.2502E-02-1.9965E-01 7.0655E-01<_>0 -1 1180 1.9828E-02-6.9136E-02 6.1643E-01<_>0 -1 1181 -3.3560E-02-1.2741E+00 -2.5673E-02<_>0 -1 1182 6.3543E-021.2404E-01 -1.0776E+00<_>0 -1 1183 2.1933E-021.4952E-02 -7.1023E-01<_>0 -1 1184 -7.8425E-026.2034E-01 3.3611E-02<_>0 -1 1185 1.4390E-02-3.6325E-01 1.7308E-01<_>0 -1 1186 -6.7310E-025.2374E-01 1.2800E-02<_>0 -1 1187 1.3047E-01-1.7122E-01 1.1235E+00<_>0 -1 1188 -4.6246E-02-1.1908E+00 1.7426E-01<_>0 -1 1189 -2.9842E-028.3931E-01 -1.8064E-01<_>0 -1 1190 -3.8100E-043.5533E-01 -2.3842E-01<_>0 -1 1191 -2.2379E-02-8.7944E-01 -7.8400E-04<_>0 -1 1192 -1.5570E-03-1.4253E-01 2.5876E-01<_>0 -1 1193 1.2013E-02-2.9015E-01 2.6051E-01<_>0 -1 1194 2.4385E-02-3.1439E-02 5.8696E-01<_>0 -1 1195 -4.7181E-026.9430E-01 -2.1816E-01<_>0 -1 1196 -2.4894E-02-6.4599E-01 1.5612E-01<_>0 -1 1197 2.1945E-02-2.7742E-02 -1.1347E+00<_>0 -1 1198 1.8810E-01-1.0076E-02 1.2429E+00<_>0 -1 1199 -7.7872E-028.5008E-01 -1.9015E-01<_>0 -1 1200 -4.8769E-02-2.0763E+00 1.2179E-01<_>0 -1 1201 -1.7115E-02-8.5687E-01 7.8760E-03<_>0 -1 1202 -2.7500E-033.8645E-01 -1.1391E-01<_>0 -1 1203 -9.8794E-02-1.7234E+00 -5.6063E-02<_>0 -1 1204 -2.1937E-025.4749E-01 -4.2482E-02<_>0 -1 1205 6.1097E-02-3.8945E-02 -1.0808E+00<_>0 -1 1206 -2.4564E-025.8311E-01 -9.7600E-04<_>0 -1 1207 3.3752E-02-1.3796E-02 -8.4730E-01<_>0 -1 1208 3.8199E-021.5114E-01 -7.9473E-01<_>0 -1 1209 -2.0118E-025.1579E-01 -2.1445E-01<_>0 -1 1210 2.4735E-02-2.2105E-02 4.2918E-01<_>0 -1 1211 -2.4357E-02-8.6201E-01 -3.6760E-03<_>0 -1 1212 -2.6442E-02-4.5397E-01 2.2463E-01<_>0 -1 1213 -3.4430E-031.3073E-01 -3.8623E-01<_>0 -1 1214 1.0702E-011.3159E-01 -7.9307E-01<_>0 -1 1215 4.5153E-02-2.5297E-01 4.0672E-01<_>0 -1 1216 4.4350E-022.2613E-02 7.9618E-01<_>0 -1 1217 1.0840E-03-3.9158E-01 1.1639E-01<_>0 -1 1218 7.1433E-028.2467E-02 1.2531E+00<_>0 -1 1219 3.5838E-02-1.8203E-01 7.7079E-01<_>0 -1 1220 -2.0839E-02-6.1744E-01 1.5891E-01<_>0 -1 1221 4.2526E-01-4.8978E-02 -1.8422E+00<_>0 -1 1222 1.1408E-021.7918E-01 -1.5383E-01<_>0 -1 1223 -1.5365E-02-8.4017E-01 -1.0280E-03<_>0 -1 1224 -1.5212E-02-1.8996E-01 1.7131E-01<_>0 -1 1225 -1.8972E-02-7.9542E-01 6.6800E-03<_>0 -1 1226 -3.3330E-03-2.3531E-01 2.4730E-01<_>0 -1 1227 9.3248E-02-5.4758E-02 -1.8324E+00<_>0 -1 1228 -1.2555E-022.6385E-01 -3.8526E-01<_>0 -1 1229 -2.7070E-02-6.6930E-01 2.0341E-02<_>0 -1 1230 -2.3677E-026.7265E-01 -1.4344E-02<_>0 -1 1231 -1.4275E-023.0186E-01 -2.8514E-01<_>0 -1 1232 2.8097E-021.4766E-01 -1.4079E+00<_>0 -1 1233 5.0840E-02-1.8614E-01 7.9953E-01<_>0 -1 1234 1.1506E-021.9118E-01 -8.5035E-02<_>0 -1 1235 -1.4661E-024.5239E-01 -2.2205E-01<_>0 -1 1236 2.2842E-011.3488E-01 -1.2895E+00<_>0 -1 1237 1.1107E-01-2.0754E-01 5.4562E-01<_>0 -1 1238 3.2450E-033.2054E-01 -1.6404E-01<_>0 -1 1239 8.5310E-02-2.0211E-01 5.3297E-01<_>0 -1 1240 2.2048E-021.5699E-01 -1.7014E-01<_>0 -1 1241 -1.5677E-02-6.2863E-01 4.0762E-02<_>0 -1 1242 3.3113E-011.6609E-01 -1.0326E+00<_>0 -1 1243 8.8470E-03-2.5076E-01 3.1661E-01<_>0 -1 1244 4.6080E-021.5352E-01 -1.6334E+00<_>0 -1 1245 -3.7703E-025.6874E-01 -2.0103E-01<_>159-3.5940E+00<_>0 -1 1246 -8.1809E-025.7125E-01 -6.7439E-01<_>0 -1 1247 2.1761E-01-3.8610E-01 9.0344E-01<_>0 -1 1248 1.4878E-022.2242E-01 -1.2779E+00<_>0 -1 1249 5.2435E-02-2.8690E-01 7.5742E-01<_>0 -1 1250 9.1430E-03-6.4880E-01 2.2269E-01<_>0 -1 1251 7.9170E-03-2.9254E-01 3.1030E-01<_>0 -1 1252 -2.6084E-024.5533E-01 -3.8501E-01<_>0 -1 1253 -2.9400E-03-5.1264E-01 2.7432E-01<_>0 -1 1254 5.7130E-021.5788E-02 -1.2133E+00<_>0 -1 1255 -6.1310E-033.9175E-01 -3.0867E-01<_>0 -1 1256 -4.0405E-021.1902E+00 -2.0347E-01<_>0 -1 1257 -2.0297E-02-6.8239E-01 2.0459E-01<_>0 -1 1258 -1.7189E-02-8.4940E-01 3.8433E-02<_>0 -1 1259 -2.4216E-02-1.1039E+00 1.5975E-01<_>0 -1 1260 5.6869E-02-1.9595E-01 1.1807E+00<_>0 -1 1261 3.6200E-04-4.0848E-01 3.2939E-01<_>0 -1 1262 9.9790E-03-2.9673E-01 4.1548E-01<_>0 -1 1263 -5.2625E-02-1.3069E+00 1.7863E-01<_>0 -1 1264 -1.3749E-022.3666E-01 -4.4537E-01<_>0 -1 1265 -3.0517E-022.9018E-01 -1.1210E-01<_>0 -1 1266 -3.0038E-01-2.4238E+00 -4.2831E-02<_>0 -1 1267 -3.5991E-028.8206E-01 -4.7013E-02<_>0 -1 1268 -5.5112E-028.0119E-01 -2.0491E-01<_>0 -1 1269 3.3762E-021.4618E-01 -1.1349E+00<_>0 -1 1270 -8.2710E-03-8.1605E-01 1.8988E-02<_>0 -1 1271 -5.4400E-03-7.0981E-01 2.2344E-01<_>0 -1 1272 3.1060E-03-7.2809E-01 4.0225E-02<_>0 -1 1273 5.3652E-021.7171E-01 -1.1164E+00<_>0 -1 1274 -1.2541E-012.7680E+00 -1.4612E-01<_>0 -1 1275 9.2542E-021.1610E-01 -3.9636E+00<_>0 -1 1276 3.8514E-02-7.6400E-03 -9.8781E-01<_>0 -1 1277 -2.0200E-032.3060E-01 -7.4970E-01<_>0 -1 1278 9.7600E-03-3.1138E-01 3.0288E-01<_>0 -1 1279 2.4095E-02-4.9530E-02 5.2690E-01<_>0 -1 1280 -1.7982E-02-1.1611E+00 -5.7000E-03<_>0 -1 1281 -1.0555E-02-2.7189E-01 2.3598E-01<_>0 -1 1282 -7.2890E-03-5.4219E-01 8.1914E-02<_>0 -1 1283 2.3939E-021.7976E-01 -6.7049E-01<_>0 -1 1284 -1.8366E-026.2664E-01 -2.0970E-01<_>0 -1 1285 1.5716E-022.4194E-01 -1.0444E+00<_>0 -1 1286 -4.8804E-02-9.4061E-01 -3.7520E-03<_>0 -1 1287 6.7130E-03-7.5432E-02 6.1575E-01<_>0 -1 1288 9.7770E-033.9285E-02 -8.4810E-01<_>0 -1 1289 1.4745E-021.6969E-01 -5.0906E-01<_>0 -1 1290 9.7079E-02-3.3103E-02 -1.2706E+00<_>0 -1 1291 4.8286E-029.4330E-02 2.7203E+00<_>0 -1 1292 9.7810E-03-3.9533E-01 1.5364E-01<_>0 -1 1293 -3.9894E-02-2.2767E-01 1.3914E-01<_>0 -1 1294 2.2848E-02-2.7392E-01 3.4200E-01<_>0 -1 1295 6.7180E-03-1.0874E-01 4.8125E-01<_>0 -1 1296 5.9600E-02-4.9522E-02 -2.0117E+00<_>0 -1 1297 6.9340E-031.5037E-01 -1.1272E-01<_>0 -1 1298 1.5757E-02-2.0885E-02 -1.1652E+00<_>0 -1 1299 -4.9690E-02-8.0213E-01 1.4372E-01<_>0 -1 1300 5.2347E-02-2.0837E-01 6.1678E-01<_>0 -1 1301 2.2431E-022.0306E-01 -7.5326E-01<_>0 -1 1302 4.1142E-02-1.8118E-01 1.0033E+00<_>0 -1 1303 -2.1632E-024.9999E-01 -3.4663E-02<_>0 -1 1304 -8.2808E-021.1712E+00 -1.8434E-01<_>0 -1 1305 8.5060E-03-6.3225E-02 2.9025E-01<_>0 -1 1306 7.8905E-02-2.3275E-01 5.9696E-01<_>0 -1 1307 -9.0207E-02-8.2212E-01 1.7772E-01<_>0 -1 1308 -2.9269E-026.0861E-01 -2.1469E-01<_>0 -1 1309 6.9500E-03-4.2666E-02 6.0512E-01<_>0 -1 1310 -8.0630E-03-1.1508E+00 -2.7286E-02<_>0 -1 1311 1.9596E-02-9.1880E-03 5.6858E-01<_>0 -1 1312 -1.4885E-023.7659E-01 -2.7150E-01<_>0 -1 1313 2.5217E-02-9.9991E-02 2.4665E-01<_>0 -1 1314 -1.5856E-026.6827E-01 -2.0615E-01<_>0 -1 1315 2.9441E-021.5832E-01 -7.6061E-01<_>0 -1 1316 -8.5280E-033.8212E-01 -2.5408E-01<_>0 -1 1317 2.4422E-021.5105E-01 -2.8753E-01<_>0 -1 1318 -3.3887E-02-6.8003E-01 3.4327E-02<_>0 -1 1319 -2.0810E-032.5414E-01 -2.6859E-01<_>0 -1 1320 3.0359E-02-3.0842E-02 -1.1477E+00<_>0 -1 1321 4.0210E-03-3.5254E-01 2.9868E-01<_>0 -1 1322 2.7681E-02-3.8149E-02 -1.3262E+00<_>0 -1 1323 7.9040E-03-2.3737E-02 7.0503E-01<_>0 -1 1324 4.4031E-021.0675E-01 -4.5261E-01<_>0 -1 1325 -3.2371E-024.6675E-01 -6.1547E-02<_>0 -1 1326 2.0933E-02-2.8448E-01 4.3846E-01<_>0 -1 1327 2.5228E-02-2.2537E-02 7.0389E-01<_>0 -1 1328 6.5520E-03-3.2555E-01 2.4024E-01<_>0 -1 1329 -5.8558E-02-1.2228E+00 1.1669E-01<_>0 -1 1330 3.1900E-02-1.9305E-02 -1.0973E+00<_>0 -1 1331 -3.0445E-026.5583E-01 7.5091E-02<_>0 -1 1332 1.4933E-02-5.2156E-01 1.1523E-01<_>0 -1 1333 -4.9008E-02-7.8304E-01 1.6657E-01<_>0 -1 1334 8.3159E-02-2.6880E-03 -8.5282E-01<_>0 -1 1335 2.3903E-02-5.1011E-02 4.1999E-01<_>0 -1 1336 1.6429E-021.9233E-02 -6.5049E-01<_>0 -1 1337 -1.1838E-02-6.2410E-01 1.5411E-01<_>0 -1 1338 -1.6800E-041.7589E-01 -3.4339E-01<_>0 -1 1339 1.9194E-024.3419E-02 7.9069E-01<_>0 -1 1340 -1.0032E-024.5649E-01 -2.2495E-01<_>0 -1 1341 -1.4004E-023.3571E-01 -4.8800E-03<_>0 -1 1342 -1.0320E-01-2.3378E+00 -5.8933E-02<_>0 -1 1343 -9.5697E-02-6.6154E-01 2.0099E-01<_>0 -1 1344 -4.1481E-024.5939E-01 -2.2314E-01<_>0 -1 1345 2.4100E-03-2.6899E-01 2.4923E-01<_>0 -1 1346 1.0725E-01-1.8640E-01 7.2770E-01<_>0 -1 1347 3.1870E-03-2.4609E-02 2.8644E-01<_>0 -1 1348 2.9167E-02-3.4683E-02 -1.1163E+00<_>0 -1 1349 1.1287E-026.3760E-03 6.6632E-01<_>0 -1 1350 -1.2001E-024.2420E-01 -2.6280E-01<_>0 -1 1351 -1.2696E-02-2.1957E-02 1.8937E-01<_>0 -1 1352 2.4597E-02-3.4964E-02 -1.0989E+00<_>0 -1 1353 4.5953E-021.1110E-01 -2.9306E+00<_>0 -1 1354 -2.7241E-022.9102E-01 -2.7408E-01<_>0 -1 1355 4.0064E-021.1878E-01 -6.2802E-01<_>0 -1 1356 2.3055E-021.4814E-01 -3.7007E-01<_>0 -1 1357 -2.3737E-02-5.3725E-01 1.9358E-01<_>0 -1 1358 7.7522E-02-6.0194E-02 -1.9490E+00<_>0 -1 1359 -1.3345E-02-4.5230E-01 1.8742E-01<_>0 -1 1360 -2.1720E-021.2144E+00 -1.5366E-01<_>0 -1 1361 -7.1475E-02-2.3047E+00 1.1000E-01<_>0 -1 1362 -5.5000E-03-7.1855E-01 2.0101E-02<_>0 -1 1363 2.6741E-027.3545E-02 9.8786E-01<_>0 -1 1364 -3.9408E-02-1.2227E+00 -4.3507E-02<_>0 -1 1365 2.5889E-021.3409E-01 -1.1771E+00<_>0 -1 1366 4.8925E-02-3.0810E-02 -9.3480E-01<_>0 -1 1367 3.6893E-021.3334E-01 -1.4998E+00<_>0 -1 1368 7.8930E-02-1.4539E-01 1.5632E+00<_>0 -1 1369 2.9006E-021.9384E-01 -6.7643E-01<_>0 -1 1370 6.3090E-03-3.7465E-01 1.0858E-01<_>0 -1 1371 -6.5831E-028.1059E-01 3.0202E-02<_>0 -1 1372 -6.8965E-028.3773E-01 -1.7141E-01<_>0 -1 1373 -1.1669E-01-9.4647E-01 1.3123E-01<_>0 -1 1374 -1.3060E-034.6008E-02 -5.2012E-01<_>0 -1 1375 -4.4559E-02-1.9424E+00 1.3201E-01<_>0 -1 1376 5.1033E-02-2.1481E-01 4.8674E-01<_>0 -1 1377 -3.1578E-025.9990E-01 7.9160E-03<_>0 -1 1378 2.1020E-02-2.2070E-01 5.4046E-01<_>0 -1 1379 -1.3824E-016.2958E-01 -2.1713E-02<_>0 -1 1380 5.2229E-02-2.3361E-01 4.9761E-01<_>0 -1 1381 2.5884E-021.8042E-01 -2.2039E-01<_>0 -1 1382 -1.2139E-02-6.9732E-01 1.5712E-02<_>0 -1 1383 -2.4238E-023.4593E-01 7.1470E-02<_>0 -1 1384 -2.5272E-02-8.7583E-01 -9.8240E-03<_>0 -1 1385 1.2597E-022.3650E-01 -2.8731E-01<_>0 -1 1386 5.7331E-02-6.1531E-02 -2.2326E+00<_>0 -1 1387 1.6671E-02-1.9850E-01 4.0811E-01<_>0 -1 1388 -2.2819E-029.6488E-01 -2.0246E-01<_>0 -1 1389 3.7000E-05-5.8909E-02 2.7055E-01<_>0 -1 1390 -7.6700E-03-4.5317E-01 8.9628E-02<_>0 -1 1391 9.4086E-021.1605E-01 -1.0951E+00<_>0 -1 1392 -6.2267E-021.8097E+00 -1.4773E-01<_>0 -1 1393 1.7416E-022.3068E-01 -4.2418E-01<_>0 -1 1394 -2.2066E-024.9270E-01 -2.0631E-01<_>0 -1 1395 -1.0404E-026.0924E-01 2.8130E-02<_>0 -1 1396 -9.3670E-034.0171E-01 -2.1682E-01<_>0 -1 1397 -2.9040E-02-8.4877E-01 1.4247E-01<_>0 -1 1398 -2.1062E-02-7.9198E-01 -1.2596E-02<_>0 -1 1399 -3.7001E-02-6.7489E-01 1.2830E-01<_>0 -1 1400 1.0736E-023.6780E-02 -6.3393E-01<_>0 -1 1401 1.6368E-011.3804E-01 -4.7189E-01<_>0 -1 1402 9.4918E-02-1.3856E-01 1.9492E+00<_>0 -1 1403 3.5262E-021.3722E-01 -2.1187E+00<_>0 -1 1404 1.2811E-02-2.0008E-01 4.9508E-01<_>155-3.3934E+00<_>0 -1 1405 1.3904E-01-4.6581E-01 7.6432E-01<_>0 -1 1406 1.1917E-02-9.4399E-01 3.9726E-01<_>0 -1 1407 -1.0007E-023.2719E-01 -6.3367E-01<_>0 -1 1408 -6.0480E-032.7428E-01 -5.7447E-01<_>0 -1 1409 -1.2490E-032.3629E-01 -6.8594E-01<_>0 -1 1410 3.2382E-02-5.7630E-01 2.7493E-01<_>0 -1 1411 -1.3958E-02-6.1062E-01 2.4542E-01<_>0 -1 1412 1.1160E-03-5.6539E-01 2.7179E-01<_>0 -1 1413 2.7000E-05-8.0236E-01 1.1509E-01<_>0 -1 1414 -2.5700E-04-8.1206E-01 2.3845E-01<_>0 -1 1415 4.0460E-031.3910E-01 -6.6163E-01<_>0 -1 1416 1.4356E-02-1.6485E-01 4.1902E-01<_>0 -1 1417 -5.5375E-021.4426E+00 -1.8820E-01<_>0 -1 1418 9.3595E-021.3548E-01 -9.1636E-01<_>0 -1 1419 2.6625E-02-3.3748E-01 3.9234E-01<_>0 -1 1420 3.7470E-03-1.1615E-01 4.4399E-01<_>0 -1 1421 -3.1886E-02-9.9498E-01 1.6120E-03<_>0 -1 1422 -2.2600E-02-4.8067E-01 1.7007E-01<_>0 -1 1423 2.5202E-023.5580E-02 -8.0215E-01<_>0 -1 1424 -3.1037E-02-1.0895E+00 1.8082E-01<_>0 -1 1425 -2.6476E-029.5671E-01 -2.1049E-01<_>0 -1 1426 -1.3854E-02-1.0370E+00 2.2167E-01<_>0 -1 1427 -6.2925E-029.0199E-01 -1.9085E-01<_>0 -1 1428 -4.4751E-02-1.0119E+00 1.4691E-01<_>0 -1 1429 -2.0428E-026.1624E-01 -2.3553E-01<_>0 -1 1430 -8.0330E-03-8.3280E-02 2.1729E-01<_>0 -1 1431 8.7280E-036.5459E-02 -6.0319E-01<_>0 -1 1432 -2.7202E-02-9.3447E-01 1.5270E-01<_>0 -1 1433 -1.6471E-02-8.4177E-01 1.3332E-02<_>0 -1 1434 -1.3744E-026.0567E-01 -9.2021E-02<_>0 -1 1435 2.9165E-02-2.8114E-02 -1.4015E+00<_>0 -1 1436 3.7457E-021.3081E-01 -4.9382E-01<_>0 -1 1437 -2.5070E-02-1.1289E+00 -1.4600E-02<_>0 -1 1438 -6.3812E-027.5872E-01 -1.8200E-03<_>0 -1 1439 -9.3900E-032.9936E-01 -2.9488E-01<_>0 -1 1440 -7.6000E-041.9725E-02 1.9994E-01<_>0 -1 1441 -2.1741E-02-8.5248E-01 4.9170E-02<_>0 -1 1442 -1.7870E-02-5.9986E-02 1.5223E-01<_>0 -1 1443 -2.4831E-023.5603E-01 -2.6260E-01<_>0 -1 1444 1.5716E-011.5600E-04 1.0429E+00<_>0 -1 1445 6.9027E-02-3.3007E-02 -1.1797E+00<_>0 -1 1446 -1.1022E-025.8988E-01 -5.7648E-02<_>0 -1 1447 -1.3835E-025.9503E-01 -2.4419E-01<_>0 -1 1448 -3.0941E-02-1.1724E+00 1.6907E-01<_>0 -1 1449 2.1258E-02-1.8901E-02 -1.0685E+00<_>0 -1 1450 9.3080E-021.6306E-01 -1.3375E+00<_>0 -1 1451 2.9636E-02-2.2525E-01 4.5400E-01<_>0 -1 1452 -1.2200E-042.7409E-01 -3.7371E-01<_>0 -1 1453 -4.2098E-02-7.5829E-01 1.7137E-02<_>0 -1 1454 -2.2505E-02-2.2759E-01 2.3699E-01<_>0 -1 1455 -1.2863E-021.9252E-01 -3.2127E-01<_>0 -1 1456 2.7860E-021.6724E-01 -1.0209E+00<_>0 -1 1457 -2.7808E-021.2825E+00 -1.7225E-01<_>0 -1 1458 -6.1630E-03-5.4073E-01 2.3886E-01<_>0 -1 1459 -2.0436E-026.3355E-01 -2.1091E-01<_>0 -1 1460 -1.2308E-02-4.9778E-01 1.7403E-01<_>0 -1 1461 -4.0494E-02-1.1849E+00 -3.3891E-02<_>0 -1 1462 2.9657E-022.1741E-02 1.0070E+00<_>0 -1 1463 6.8380E-032.9218E-02 -5.9906E-01<_>0 -1 1464 1.6165E-02-2.1001E-01 3.7637E-01<_>0 -1 1465 5.0193E-022.5320E-03 -7.1668E-01<_>0 -1 1466 1.9680E-03-2.1921E-01 3.2299E-01<_>0 -1 1467 2.4980E-02-9.6840E-03 -7.7573E-01<_>0 -1 1468 -1.5810E-024.4638E-01 -6.1760E-02<_>0 -1 1469 3.7207E-02-2.0495E-01 5.7722E-01<_>0 -1 1470 -7.9265E-02-7.6745E-01 1.2550E-01<_>0 -1 1471 -1.7152E-02-1.4122E+00 -5.1704E-02<_>0 -1 1472 3.2740E-021.9334E-01 -6.3634E-01<_>0 -1 1473 -1.1757E-018.4325E-01 -1.8019E-01<_>0 -1 1474 1.2057E-011.2530E-01 -2.1214E+00<_>0 -1 1475 4.2780E-03-4.6604E-01 8.9644E-02<_>0 -1 1476 -7.2545E-025.1827E-01 1.6824E-02<_>0 -1 1477 1.7711E-01-3.0910E-02 -1.1047E+00<_>0 -1 1478 8.4230E-032.4446E-01 -3.8613E-01<_>0 -1 1479 -1.3035E-029.8004E-01 -1.7017E-01<_>0 -1 1480 1.8912E-022.0248E-01 -3.8546E-01<_>0 -1 1481 2.1448E-02-2.5717E-01 3.5181E-01<_>0 -1 1482 6.3357E-021.6995E-01 -9.1384E-01<_>0 -1 1483 -3.2436E-02-8.5682E-01 -2.1681E-02<_>0 -1 1484 -2.3565E-025.6116E-01 -2.2400E-04<_>0 -1 1485 1.8789E-02-2.5460E-01 3.4513E-01<_>0 -1 1486 3.1042E-027.5720E-03 3.4800E-01<_>0 -1 1487 -1.1227E-02-6.0220E-01 4.2815E-02<_>0 -1 1488 -1.2846E-024.2020E-01 -5.3801E-02<_>0 -1 1489 -1.2792E-022.2725E-01 -3.2398E-01<_>0 -1 1490 6.8652E-029.3532E-02 10.<_>0 -1 1491 5.2790E-03-2.6926E-01 3.3303E-01<_>0 -1 1492 -3.8779E-02-7.2365E-01 1.7807E-01<_>0 -1 1493 6.1820E-03-3.5119E-01 1.6586E-01<_>0 -1 1494 1.7515E-011.1623E-01 -1.5419E+00<_>0 -1 1495 1.1628E-01-9.1480E-03 -9.9843E-01<_>0 -1 1496 -2.2964E-022.0565E-01 1.5432E-02<_>0 -1 1497 -5.1410E-025.8072E-01 -2.0118E-01<_>0 -1 1498 2.2474E-011.8729E-02 1.0829E+00<_>0 -1 1499 9.4860E-03-3.3171E-01 1.9903E-01<_>0 -1 1500 -1.1846E-011.3711E+00 6.8927E-02<_>0 -1 1501 3.7811E-02-9.3600E-04 -8.3997E-01<_>0 -1 1502 2.2202E-02-1.1964E-02 3.6674E-01<_>0 -1 1503 -3.6366E-023.7867E-01 -2.7715E-01<_>0 -1 1504 -1.3185E-01-2.7481E+00 1.0667E-01<_>0 -1 1505 -4.1656E-024.7524E-01 -2.3250E-01<_>0 -1 1506 -3.3152E-02-5.7929E-01 1.7434E-01<_>0 -1 1507 1.5770E-02-1.1284E-02 -8.3701E-01<_>0 -1 1508 -3.9363E-023.4822E-01 -1.7455E-01<_>0 -1 1509 -6.7849E-021.4226E+00 -1.4766E-01<_>0 -1 1510 -2.6775E-022.3947E-01 1.3272E-02<_>0 -1 1511 3.9919E-02-9.0000E-03 -7.5939E-01<_>0 -1 1512 1.0066E-01-1.8685E-02 7.6245E-01<_>0 -1 1513 -8.1022E-02-9.0439E-01 -8.5880E-03<_>0 -1 1514 -2.1258E-02-2.1320E-01 2.1920E-01<_>0 -1 1515 -1.0631E-021.9598E-01 -3.5768E-01<_>0 -1 1516 8.1300E-04-9.2795E-02 2.6146E-01<_>0 -1 1517 3.4650E-03-5.5336E-01 2.7386E-02<_>0 -1 1518 1.8836E-021.8446E-01 -6.6934E-01<_>0 -1 1519 -2.5632E-021.9383E+00 -1.4709E-01<_>0 -1 1520 -4.0940E-03-2.6452E-01 2.0733E-01<_>0 -1 1521 -8.9200E-04-5.5032E-01 5.0375E-02<_>0 -1 1522 -4.9518E-02-2.5615E+00 1.3142E-01<_>0 -1 1523 1.1681E-02-2.4820E-01 3.9983E-01<_>0 -1 1524 3.4564E-021.6179E-01 -7.1419E-01<_>0 -1 1525 -8.2910E-032.2180E-01 -2.9182E-01<_>0 -1 1526 -2.2358E-023.1044E-01 -2.7280E-03<_>0 -1 1527 -3.0801E-02-9.5673E-01 -8.3400E-03<_>0 -1 1528 4.3779E-021.2557E-01 -1.1760E+00<_>0 -1 1529 4.3046E-02-5.8877E-02 -1.8568E+00<_>0 -1 1530 2.7189E-024.2858E-02 3.9037E-01<_>0 -1 1531 9.4150E-03-4.3567E-02 -1.1094E+00<_>0 -1 1532 9.4312E-024.0257E-02 9.8442E-01<_>0 -1 1533 1.7025E-012.9510E-02 -6.9509E-01<_>0 -1 1534 -4.7148E-021.0339E+00 6.7602E-02<_>0 -1 1535 1.1186E-01-6.8683E-02 -2.4986E+00<_>0 -1 1536 -1.4354E-02-5.9482E-01 1.5002E-01<_>0 -1 1537 3.4024E-02-6.4823E-02 -2.1383E+00<_>0 -1 1538 2.1602E-025.5310E-02 7.8293E-01<_>0 -1 1539 2.1772E-02-7.1280E-03 -7.2148E-01<_>0 -1 1540 8.2417E-021.4609E-01 -1.3637E+00<_>0 -1 1541 8.4672E-02-1.7785E-01 7.2858E-01<_>0 -1 1542 -5.5128E-02-5.9402E-01 1.9358E-01<_>0 -1 1543 -6.4823E-02-1.0784E+00 -4.0734E-02<_>0 -1 1544 -2.2769E-027.7900E-01 3.4960E-03<_>0 -1 1545 5.4756E-02-6.5684E-02 -1.8188E+00<_>0 -1 1546 -8.9000E-05-1.7892E-02 2.0768E-01<_>0 -1 1547 9.8362E-02-5.5947E-02 -1.4154E+00<_>0 -1 1548 -7.0930E-033.4135E-01 -1.2090E-01<_>0 -1 1549 5.0278E-02-2.6287E-01 2.5797E-01<_>0 -1 1550 -5.7870E-03-1.3179E-01 1.7350E-01<_>0 -1 1551 1.3974E-022.8518E-02 -6.1152E-01<_>0 -1 1552 2.1450E-022.6182E-02 3.0307E-01<_>0 -1 1553 -2.9214E-024.4941E-01 -2.2803E-01<_>0 -1 1554 4.8100E-04-1.9880E-01 2.0744E-01<_>0 -1 1555 1.7110E-03-5.4037E-01 6.7866E-02<_>0 -1 1556 8.6660E-03-1.3128E-02 5.2298E-01<_>0 -1 1557 6.3658E-026.8299E-02 -4.9235E-01<_>0 -1 1558 -2.7968E-026.8184E-01 7.8781E-02<_>0 -1 1559 4.8954E-02-2.0622E-01 5.0388E-01<_>169-3.2397E+00<_>0 -1 1560 -2.9313E-027.1285E-01 -5.8231E-01<_>0 -1 1561 1.2415E-01-3.6863E-01 6.0067E-01<_>0 -1 1562 7.9350E-03-8.6008E-01 2.1725E-01<_>0 -1 1563 3.0366E-02-2.7187E-01 6.1248E-01<_>0 -1 1564 2.5218E-02-3.4748E-01 5.0428E-01<_>0 -1 1565 1.0014E-02-3.1899E-01 4.1377E-01<_>0 -1 1566 -1.6775E-02-6.9048E-01 9.4831E-02<_>0 -1 1567 -2.6950E-03-2.0830E-01 2.3737E-01<_>0 -1 1568 4.2258E-02-4.9367E-01 1.8171E-01<_>0 -1 1569 -4.8505E-021.3430E+00 3.9769E-02<_>0 -1 1570 2.8993E-024.6496E-02 -8.1643E-01<_>0 -1 1571 -4.0089E-02-7.1198E-01 2.2554E-01<_>0 -1 1572 -4.1022E-021.0058E+00 -1.9690E-01<_>0 -1 1573 1.1838E-02-1.2600E-02 8.0767E-01<_>0 -1 1574 -2.1328E-02-8.2024E-01 2.0525E-02<_>0 -1 1575 -2.3905E-025.4211E-01 -7.4767E-02<_>0 -1 1576 1.8009E-02-3.3828E-01 4.2359E-01<_>0 -1 1577 -4.3614E-02-1.1983E+00 1.5566E-01<_>0 -1 1578 -9.2450E-03-8.9030E-01 1.1004E-02<_>0 -1 1579 4.7485E-021.6664E-01 -9.0764E-01<_>0 -1 1580 -1.4234E-026.2695E-01 -2.5791E-01<_>0 -1 1581 3.8010E-03-2.8230E-01 2.6625E-01<_>0 -1 1582 3.4330E-03-6.3772E-01 9.8423E-02<_>0 -1 1583 -2.9221E-02-7.6770E-01 2.2635E-01<_>0 -1 1584 -6.4950E-034.5600E-01 -2.6529E-01<_>0 -1 1585 -3.0034E-02-7.6551E-01 1.4009E-01<_>0 -1 1586 7.8360E-034.6756E-02 -7.2356E-01<_>0 -1 1587 8.8550E-03-4.9142E-02 5.1473E-01<_>0 -1 1588 9.5974E-02-2.0069E-02 -1.0851E+00<_>0 -1 1589 -3.2877E-02-9.5875E-01 1.4544E-01<_>0 -1 1590 -1.3384E-02-7.0014E-01 2.9158E-02<_>0 -1 1591 1.5236E-02-2.8236E-01 2.5368E-01<_>0 -1 1592 1.2054E-02-2.5303E-01 4.6527E-01<_>0 -1 1593 -7.6295E-02-6.9916E-01 1.3217E-01<_>0 -1 1594 -1.2040E-024.5895E-01 -2.3856E-01<_>0 -1 1595 2.1916E-021.8269E-01 -6.1630E-01<_>0 -1 1596 -2.7330E-03-6.3258E-01 3.4219E-02<_>0 -1 1597 -4.8652E-02-1.0298E+00 1.7387E-01<_>0 -1 1598 -1.0464E-023.4757E-01 -2.7464E-01<_>0 -1 1599 -6.6550E-03-2.8980E-01 2.4038E-01<_>0 -1 1600 8.5470E-03-4.4341E-01 1.4267E-01<_>0 -1 1601 1.9914E-021.7740E-01 -2.4096E-01<_>0 -1 1602 2.2013E-02-1.0812E-02 -9.4691E-01<_>0 -1 1603 -5.2179E-021.6547E+00 9.6487E-02<_>0 -1 1604 1.9699E-02-6.7560E-03 -8.6312E-01<_>0 -1 1605 2.3040E-02-2.3520E-03 3.8531E-01<_>0 -1 1606 -1.5038E-02-6.1906E-01 3.1078E-02<_>0 -1 1607 -4.9956E-027.0657E-01 4.7881E-02<_>0 -1 1608 -6.9270E-023.9213E-01 -2.3848E-01<_>0 -1 1609 4.7400E-03-2.4309E-02 2.5386E-01<_>0 -1 1610 -3.3924E-024.6930E-01 -2.3322E-01<_>0 -1 1611 -1.6231E-023.2319E-01 -2.0546E-01<_>0 -1 1612 -5.0193E-02-1.2278E+00 -4.0798E-02<_>0 -1 1613 5.6944E-024.5184E-02 6.0198E-01<_>0 -1 1614 4.0937E-02-1.6773E-01 8.9819E-01<_>0 -1 1615 -3.0840E-033.3716E-01 -2.7241E-01<_>0 -1 1616 -3.2600E-02-8.5447E-01 1.9665E-02<_>0 -1 1617 9.8481E-025.4742E-02 6.3827E-01<_>0 -1 1618 -3.8185E-025.2275E-01 -2.3385E-01<_>0 -1 1619 -4.5917E-026.2829E-01 3.2859E-02<_>0 -1 1620 -1.1955E-01-6.1573E-01 3.4680E-02<_>0 -1 1621 -1.2044E-01-8.4380E-01 1.6531E-01<_>0 -1 1622 7.0619E-02-6.3261E-02 -1.9864E+00<_>0 -1 1623 8.4890E-03-1.7663E-01 3.8011E-01<_>0 -1 1624 2.2711E-02-2.7606E-02 -9.1921E-01<_>0 -1 1625 4.9700E-04-2.4293E-01 2.2879E-01<_>0 -1 1626 3.4652E-02-2.3706E-01 5.4011E-01<_>0 -1 1627 -4.4700E-033.9079E-01 -1.2694E-01<_>0 -1 1628 2.3643E-02-2.6664E-01 3.2313E-01<_>0 -1 1629 1.2813E-021.7541E-01 -6.0788E-01<_>0 -1 1630 -1.1251E-02-1.0853E+00 -2.8046E-02<_>0 -1 1631 -4.1535E-027.1887E-01 2.7982E-02<_>0 -1 1632 -9.3471E-02-1.1906E+00 -4.4811E-02<_>0 -1 1633 -2.7250E-026.2942E-01 9.5040E-03<_>0 -1 1634 -2.1760E-021.3234E+00 -1.5027E-01<_>0 -1 1635 -9.6890E-03-3.3947E-01 1.7086E-01<_>0 -1 1636 6.9396E-02-2.5658E-01 4.7652E-01<_>0 -1 1637 3.1209E-021.4154E-01 -3.4942E-01<_>0 -1 1638 -4.9727E-02-1.1676E+00 -4.0758E-02<_>0 -1 1639 -2.0302E-02-3.9486E-01 1.5815E-01<_>0 -1 1640 -1.5367E-024.9300E-01 -2.0092E-01<_>0 -1 1641 -5.0735E-021.8736E+00 8.6730E-02<_>0 -1 1642 -2.0726E-02-8.8938E-01 -7.3200E-03<_>0 -1 1643 -3.0994E-02-1.1665E+00 1.4275E-01<_>0 -1 1644 -4.4270E-03-6.6815E-01 4.4120E-03<_>0 -1 1645 -4.5744E-02-4.7955E-01 1.5122E-01<_>0 -1 1646 1.6699E-021.2049E-01 -4.5236E-01<_>0 -1 1647 3.2210E-03-7.7615E-02 2.7847E-01<_>0 -1 1648 2.4434E-02-1.9987E-01 6.7254E-01<_>0 -1 1649 -7.9678E-029.2222E-01 9.2558E-02<_>0 -1 1650 4.4530E-02-2.6691E-01 3.3321E-01<_>0 -1 1651 -1.2528E-01-5.4253E-01 1.3976E-01<_>0 -1 1652 1.7972E-021.8220E-02 -6.8049E-01<_>0 -1 1653 1.9184E-02-1.2584E-02 5.4127E-01<_>0 -1 1654 4.0024E-02-1.7639E-01 7.8810E-01<_>0 -1 1655 1.3559E-022.0738E-01 -4.7744E-01<_>0 -1 1656 1.6221E-022.3077E-02 -6.1182E-01<_>0 -1 1657 1.1229E-02-1.7728E-02 4.1764E-01<_>0 -1 1658 3.9193E-02-1.8948E-01 7.4019E-01<_>0 -1 1659 -9.5540E-034.0947E-01 -1.3509E-01<_>0 -1 1660 2.7879E-02-2.0351E-01 6.1625E-01<_>0 -1 1661 -2.3601E-02-1.6967E+00 1.4633E-01<_>0 -1 1662 2.6930E-02-3.0402E-02 -1.0909E+00<_>0 -1 1663 2.9000E-04-2.0076E-01 2.2314E-01<_>0 -1 1664 -4.1125E-02-4.5242E-01 5.7392E-02<_>0 -1 1665 6.6790E-032.3825E-01 -2.1262E-01<_>0 -1 1666 4.7865E-02-1.8195E-01 6.1918E-01<_>0 -1 1667 -3.1680E-03-2.7393E-01 2.5017E-01<_>0 -1 1668 -8.6230E-03-4.6280E-01 4.2398E-02<_>0 -1 1669 -7.4350E-034.1797E-01 -1.7080E-03<_>0 -1 1670 -1.8770E-031.4602E-01 -3.3721E-01<_>0 -1 1671 -8.6226E-027.5143E-01 1.0712E-02<_>0 -1 1672 4.6834E-02-1.9120E-01 4.8415E-01<_>0 -1 1673 -9.2000E-053.5220E-01 -1.7333E-01<_>0 -1 1674 -1.6344E-02-6.4398E-01 9.0680E-03<_>0 -1 1675 4.5704E-021.8216E-02 3.1971E-01<_>0 -1 1676 -2.7383E-021.0564E+00 -1.7276E-01<_>0 -1 1677 -2.7602E-022.9715E-01 -9.4600E-03<_>0 -1 1678 7.6940E-03-2.1660E-01 4.7385E-01<_>0 -1 1679 -7.0500E-042.4049E-01 -2.6776E-01<_>0 -1 1680 1.1054E-01-3.3539E-02 -1.0234E+00<_>0 -1 1681 6.8766E-02-4.3240E-03 5.7153E-01<_>0 -1 1682 1.8000E-037.7575E-02 -4.2093E-01<_>0 -1 1683 1.9232E-018.2022E-02 2.8810E+00<_>0 -1 1684 1.5742E-01-1.3708E-01 2.0890E+00<_>0 -1 1685 -4.9387E-02-1.8611E+00 1.4332E-01<_>0 -1 1686 5.1929E-02-1.8737E-01 5.4232E-01<_>0 -1 1687 4.9965E-021.4175E-01 -1.5626E+00<_>0 -1 1688 -4.2633E-021.6059E+00 -1.4713E-01<_>0 -1 1689 -3.7554E-02-8.0975E-01 1.3257E-01<_>0 -1 1690 -3.7175E-02-1.3945E+00 -5.7055E-02<_>0 -1 1691 1.3946E-023.3427E-02 5.7475E-01<_>0 -1 1692 -4.4800E-04-5.5327E-01 2.1953E-02<_>0 -1 1693 3.1993E-022.0341E-02 3.7459E-01<_>0 -1 1694 -4.2800E-034.4429E-01 -2.3000E-01<_>0 -1 1695 9.8550E-031.8316E-01 -4.0965E-01<_>0 -1 1696 9.3357E-02-6.3661E-02 -1.6929E+00<_>0 -1 1697 1.7210E-022.0154E-01 -4.6061E-01<_>0 -1 1698 8.4320E-03-3.2004E-01 1.5312E-01<_>0 -1 1699 -1.4055E-028.6882E-01 3.2575E-02<_>0 -1 1700 -7.7180E-036.3687E-01 -1.8426E-01<_>0 -1 1701 2.8005E-021.7357E-01 -4.7884E-01<_>0 -1 1702 -1.8885E-022.4102E-01 -2.6548E-01<_>0 -1 1703 -1.8585E-025.4233E-01 5.3633E-02<_>0 -1 1704 -3.6437E-022.3909E+00 -1.3635E-01<_>0 -1 1705 3.2455E-021.5911E-01 -6.7581E-01<_>0 -1 1706 5.9782E-02-2.3480E-03 -7.3054E-01<_>0 -1 1707 9.8210E-03-1.1444E-01 3.0570E-01<_>0 -1 1708 -3.5164E-02-1.0511E+00 -3.3103E-02<_>0 -1 1709 2.7430E-03-2.0135E-01 3.2754E-01<_>0 -1 1710 8.1060E-03-2.1384E-01 4.3362E-01<_>0 -1 1711 8.8943E-021.0941E-01 -4.7609E+00<_>0 -1 1712 -3.0055E-02-1.7169E+00 -6.0919E-02<_>0 -1 1713 -2.1735E-026.4779E-01 -3.2831E-02<_>0 -1 1714 3.7649E-02-1.0060E-02 -7.6569E-01<_>0 -1 1715 2.7190E-031.9889E-01 -8.2479E-02<_>0 -1 1716 -1.0548E-02-8.6614E-01 -2.5986E-02<_>0 -1 1717 1.2966E-011.3912E-01 -2.2272E+00<_>0 -1 1718 -1.7677E-023.3968E-01 -2.3990E-01<_>0 -1 1719 -7.7052E-02-2.5018E+00 1.2842E-01<_>0 -1 1720 -1.9230E-025.0641E-01 -1.9752E-01<_>0 -1 1721 -5.1223E-02-2.9333E+00 1.3859E-01<_>0 -1 1722 2.0830E-03-6.0044E-01 2.9718E-02<_>0 -1 1723 2.5418E-023.3916E-01 -1.4392E-01<_>0 -1 1724 -2.3906E-02-1.1083E+00 -4.7377E-02<_>0 -1 1725 -6.3740E-034.4534E-01 -6.7053E-02<_>0 -1 1726 -3.7699E-02-1.0407E+00 -4.1790E-02<_>0 -1 1727 2.1655E-013.3863E-02 8.2017E-01<_>0 -1 1728 -1.3401E-025.2903E-01 -1.9133E-01<_>196-3.2104E+00<_>0 -1 1729 7.1269E-02-5.3631E-01 6.0715E-01<_>0 -1 1730 5.6111E-02-5.0142E-01 4.3976E-01<_>0 -1 1731 4.0464E-02-3.2922E-01 5.4835E-01<_>0 -1 1732 6.3155E-02-3.1702E-01 4.6153E-01<_>0 -1 1733 1.0321E-021.0695E-01 -9.8244E-01<_>0 -1 1734 6.2607E-02-1.4330E-01 7.1095E-01<_>0 -1 1735 -3.9416E-029.4380E-01 -2.1572E-01<_>0 -1 1736 -5.3960E-03-5.4612E-01 2.5304E-01<_>0 -1 1737 1.0773E-011.2496E-02 -1.0809E+00<_>0 -1 1738 1.6982E-02-3.1536E-01 5.1240E-01<_>0 -1 1739 3.1217E-02-4.5200E-03 -1.2443E+00<_>0 -1 1740 -2.3107E-02-7.6493E-01 2.0641E-01<_>0 -1 1741 -1.1204E-022.4093E-01 -3.5142E-01<_>0 -1 1742 -4.7480E-03-9.7008E-02 2.0638E-01<_>0 -1 1743 -1.7359E-02-7.9020E-01 2.1853E-02<_>0 -1 1744 1.8852E-02-1.0395E-01 5.4844E-01<_>0 -1 1745 7.2250E-03-4.0409E-01 2.6764E-01<_>0 -1 1746 1.8916E-022.0508E-01 -1.0206E+00<_>0 -1 1747 3.1157E-021.2400E-03 -8.7293E-01<_>0 -1 1748 2.0952E-02-5.5560E-03 8.0356E-01<_>0 -1 1749 1.1291E-02-3.6478E-01 2.2768E-01<_>0 -1 1750 -5.7011E-02-1.4296E+00 1.4322E-01<_>0 -1 1751 7.2194E-02-4.1850E-02 -1.9112E+00<_>0 -1 1752 -1.9874E-022.6425E-01 -3.2618E-01<_>0 -1 1753 -1.6693E-02-8.3908E-01 4.0800E-04<_>0 -1 1754 -3.9835E-02-4.8858E-01 1.6436E-01<_>0 -1 1755 2.7010E-02-1.8862E-01 8.3419E-01<_>0 -1 1756 -3.9420E-032.3232E-01 -7.2360E-02<_>0 -1 1757 2.2833E-02-3.5884E-02 -1.1549E+00<_>0 -1 1758 -6.8888E-02-1.7837E+00 1.5159E-01<_>0 -1 1759 4.3097E-02-2.1608E-01 5.0624E-01<_>0 -1 1760 8.6240E-03-1.7796E-01 2.8958E-01<_>0 -1 1761 1.4561E-02-1.1408E-02 -8.9402E-01<_>0 -1 1762 -1.1501E-023.0172E-01 -4.3659E-02<_>0 -1 1763 -1.0971E-01-9.5147E-01 -1.9973E-02<_>0 -1 1764 4.5228E-023.3111E-02 9.6620E-01<_>0 -1 1765 -2.7048E-029.7964E-01 -1.7262E-01<_>0 -1 1766 1.8031E-02-2.0801E-02 2.7386E-01<_>0 -1 1767 5.0525E-02-5.6803E-02 -1.7775E+00<_>0 -1 1768 -2.9924E-026.5329E-01 -2.3537E-02<_>0 -1 1769 3.8058E-022.6317E-02 -7.0666E-01<_>0 -1 1770 1.8564E-01-5.6040E-03 3.2874E-01<_>0 -1 1771 -4.0670E-033.4205E-01 -3.0172E-01<_>0 -1 1772 1.0109E-02-7.3600E-03 5.7982E-01<_>0 -1 1773 -1.1567E-02-5.2722E-01 4.6448E-02<_>0 -1 1774 -6.5650E-03-5.8529E-01 1.9102E-01<_>0 -1 1775 1.0582E-022.1073E-02 -6.8893E-01<_>0 -1 1776 -2.0304E-02-3.6401E-01 1.5339E-01<_>0 -1 1777 2.3530E-033.6164E-02 -5.9825E-01<_>0 -1 1778 -1.4690E-03-1.4708E-01 3.7508E-01<_>0 -1 1779 8.6450E-03-2.1709E-01 5.1937E-01<_>0 -1 1780 -2.4326E-02-1.0847E+00 1.4085E-01<_>0 -1 1781 7.4419E-02-1.5514E-01 1.1823E+00<_>0 -1 1782 1.7078E-024.4231E-02 9.1561E-01<_>0 -1 1783 -2.4578E-02-1.5504E+00 -5.4746E-02<_>0 -1 1784 3.0205E-021.6663E-01 -1.0001E+00<_>0 -1 1785 1.2136E-02-7.7079E-01 -4.8640E-03<_>0 -1 1786 8.6717E-021.1062E-01 -1.6858E+00<_>0 -1 1787 -4.2309E-021.1076E+00 -1.5439E-01<_>0 -1 1788 -2.6420E-032.7452E-01 -1.8456E-01<_>0 -1 1789 -5.6662E-02-8.0626E-01 -1.6928E-02<_>0 -1 1790 2.3475E-021.4188E-01 -2.5501E-01<_>0 -1 1791 -2.0803E-021.9826E-01 -3.1171E-01<_>0 -1 1792 7.2600E-03-5.0591E-02 4.1924E-01<_>0 -1 1793 3.4160E-01-1.6675E-01 9.2749E-01<_>0 -1 1794 6.2030E-03-1.2626E-01 4.0445E-01<_>0 -1 1795 3.2692E-02-3.2635E-02 -9.8940E-01<_>0 -1 1796 2.1100E-04-6.4534E-02 2.5474E-01<_>0 -1 1797 7.2100E-04-3.6619E-01 1.1973E-01<_>0 -1 1798 5.4491E-021.2073E-01 -1.0291E+00<_>0 -1 1799 -1.0141E-02-5.2177E-01 3.3735E-02<_>0 -1 1800 -1.8816E-026.5182E-01 1.3400E-03<_>0 -1 1801 -5.3480E-031.7371E-01 -3.4132E-01<_>0 -1 1802 -1.0847E-02-1.9700E-01 1.5045E-01<_>0 -1 1803 -4.9926E-02-5.0889E-01 3.0762E-02<_>0 -1 1804 1.2160E-02-6.9252E-02 1.8745E-01<_>0 -1 1805 -2.2190E-03-4.0849E-01 7.9955E-02<_>0 -1 1806 3.1580E-03-2.1125E-01 2.2366E-01<_>0 -1 1807 4.1440E-03-4.9900E-01 6.2917E-02<_>0 -1 1808 -7.3730E-03-2.0553E-01 2.2097E-01<_>0 -1 1809 5.1812E-021.8097E-01 -4.3496E-01<_>0 -1 1810 1.8340E-021.5200E-02 3.7992E-01<_>0 -1 1811 1.7491E-01-2.0921E-01 4.0013E-01<_>0 -1 1812 5.3994E-022.4752E-01 -2.6713E-01<_>0 -1 1813 -3.2033E-01-1.9094E+00 -6.6961E-02<_>0 -1 1814 -2.7060E-02-7.1371E-01 1.5905E-01<_>0 -1 1815 7.7464E-02-1.6970E-01 7.7553E-01<_>0 -1 1816 2.3772E-021.9022E-01 -6.0162E-01<_>0 -1 1817 1.1501E-027.7040E-03 -6.1730E-01<_>0 -1 1818 3.2616E-021.7159E-01 -7.0978E-01<_>0 -1 1819 -4.4383E-02-2.2606E+00 -7.3277E-02<_>0 -1 1820 -5.8476E-022.4088E+00 8.3092E-02<_>0 -1 1821 1.9304E-02-2.7082E-01 2.7370E-01<_>0 -1 1822 -4.4706E-023.1356E-01 -6.2492E-02<_>0 -1 1823 -6.0335E-02-1.4515E+00 -5.8761E-02<_>0 -1 1824 1.1667E-02-1.8085E-02 5.0480E-01<_>0 -1 1825 2.8010E-02-2.3303E-01 3.0709E-01<_>0 -1 1826 6.5397E-021.4136E-01 -5.0011E-01<_>0 -1 1827 9.6240E-03-2.2055E-01 3.9191E-01<_>0 -1 1828 2.5510E-03-1.1382E-01 2.0032E-01<_>0 -1 1829 3.1847E-022.5477E-02 -5.3326E-01<_>0 -1 1830 3.3055E-021.7808E-01 -6.2794E-01<_>0 -1 1831 4.7601E-02-1.4748E-01 1.4204E+00<_>0 -1 1832 -1.9572E-02-5.2693E-01 1.5839E-01<_>0 -1 1833 -5.4730E-028.8232E-01 -1.6628E-01<_>0 -1 1834 -2.2686E-02-4.8387E-01 1.5000E-01<_>0 -1 1835 1.0713E-01-2.1336E-01 4.2334E-01<_>0 -1 1836 -3.6380E-02-7.4198E-02 1.4589E-01<_>0 -1 1837 1.3936E-02-2.4912E-01 2.6771E-01<_>0 -1 1838 2.0992E-028.7960E-03 4.3065E-01<_>0 -1 1839 4.9119E-02-1.7592E-01 6.9283E-01<_>0 -1 1840 3.6316E-021.3145E-01 -3.3597E-01<_>0 -1 1841 4.1228E-02-4.5692E-02 -1.3516E+00<_>0 -1 1842 1.5672E-021.7544E-01 -6.0550E-02<_>0 -1 1843 -1.6286E-02-1.1308E+00 -3.9533E-02<_>0 -1 1844 -3.0230E-03-2.2454E-01 2.3628E-01<_>0 -1 1845 -1.3786E-014.5377E-01 -2.1099E-01<_>0 -1 1846 -9.6760E-03-1.5105E-01 2.0782E-01<_>0 -1 1847 -2.4840E-02-6.8350E-01 -8.0040E-03<_>0 -1 1848 -1.3964E-016.5011E-01 4.6544E-02<_>0 -1 1849 -8.2154E-024.4887E-01 -2.3592E-01<_>0 -1 1850 3.8450E-03-8.8173E-02 2.7347E-01<_>0 -1 1851 -6.6580E-03-4.6867E-01 7.7002E-02<_>0 -1 1852 -1.5898E-022.9268E-01 -2.1941E-02<_>0 -1 1853 -5.0946E-02-1.2094E+00 -4.2110E-02<_>0 -1 1854 1.6838E-02-4.5596E-02 5.0181E-01<_>0 -1 1855 1.5919E-02-2.6904E-01 2.6516E-01<_>0 -1 1856 3.6310E-03-1.3046E-01 3.1807E-01<_>0 -1 1857 -8.6145E-021.9444E+00 -1.3978E-01<_>0 -1 1858 3.3141E-021.5267E-01 -3.0866E-02<_>0 -1 1859 -3.9680E-03-7.1202E-01 -1.3844E-02<_>0 -1 1860 -2.4008E-029.2008E-01 4.6724E-02<_>0 -1 1861 8.7320E-03-2.2567E-01 3.1932E-01<_>0 -1 1862 -2.7787E-02-7.2337E-01 1.7019E-01<_>0 -1 1863 -1.9455E-011.2462E+00 -1.4736E-01<_>0 -1 1864 -1.0870E-01-1.4465E+00 1.2145E-01<_>0 -1 1865 -1.9495E-02-7.8153E-01 -2.3733E-02<_>0 -1 1866 3.0650E-03-8.5471E-01 1.6687E-01<_>0 -1 1867 5.9194E-02-1.4854E-01 1.1273E+00<_>0 -1 1868 -5.4208E-025.4727E-01 3.5524E-02<_>0 -1 1869 -3.9325E-023.6643E-01 -2.0544E-01<_>0 -1 1870 8.2279E-02-3.5008E-02 5.3994E-01<_>0 -1 1871 -7.4480E-03-6.1537E-01 -3.5320E-03<_>0 -1 1872 7.3770E-03-6.5591E-02 4.1961E-01<_>0 -1 1873 7.0780E-03-3.4130E-01 1.2537E-01<_>0 -1 1874 -1.5582E-02-3.0240E-01 2.1511E-01<_>0 -1 1875 -2.7400E-037.6553E-02 -4.1061E-01<_>0 -1 1876 -7.0600E-02-9.7356E-01 1.1242E-01<_>0 -1 1877 -1.1706E-021.8561E-01 -2.9755E-01<_>0 -1 1878 7.1500E-04-5.9650E-02 2.4825E-01<_>0 -1 1879 -3.6866E-023.2752E-01 -2.3060E-01<_>0 -1 1880 -3.2527E-02-2.9320E-01 1.5428E-01<_>0 -1 1881 -7.4814E-02-1.2144E+00 -5.2244E-02<_>0 -1 1882 4.1470E-021.3062E-01 -2.3274E+00<_>0 -1 1883 -2.8880E-02-6.6075E-01 -9.0960E-03<_>0 -1 1884 4.6382E-021.6630E-01 -6.6949E-01<_>0 -1 1885 2.5425E-01-5.4642E-02 -1.2676E+00<_>0 -1 1886 2.4000E-032.0277E-01 1.4668E-02<_>0 -1 1887 -8.2806E-02-7.8714E-01 -2.4469E-02<_>0 -1 1888 -1.1438E-022.8623E-01 -3.0894E-02<_>0 -1 1889 -1.2913E-011.7293E+00 -1.4294E-01<_>0 -1 1890 3.8553E-021.9233E-02 3.7733E-01<_>0 -1 1891 1.0191E-01-7.4534E-02 -3.3869E+00<_>0 -1 1892 -1.9068E-023.1814E-01 1.9261E-02<_>0 -1 1893 -6.0775E-027.6936E-01 -1.7644E-01<_>0 -1 1894 2.4680E-021.8396E-01 -3.0869E-01<_>0 -1 1895 2.6759E-02-2.3455E-01 3.3057E-01<_>0 -1 1896 1.4970E-021.7214E-01 -1.8249E-01<_>0 -1 1897 2.6143E-02-4.6464E-02 -1.1318E+00<_>0 -1 1898 -3.7512E-028.0404E-01 6.9660E-02<_>0 -1 1899 -5.3230E-03-8.1884E-01 -1.8225E-02<_>0 -1 1900 1.7813E-021.4958E-01 -1.8667E-01<_>0 -1 1901 -3.4010E-02-7.2852E-01 -1.6616E-02<_>0 -1 1902 -1.5953E-025.6944E-01 1.3832E-02<_>0 -1 1903 1.9744E-024.0525E-02 -4.1773E-01<_>0 -1 1904 -1.0375E-01-1.9825E+00 1.1960E-01<_>0 -1 1905 -1.9285E-025.0231E-01 -1.9746E-01<_>0 -1 1906 -1.2780E-024.0195E-01 -2.6958E-02<_>0 -1 1907 -1.6353E-02-7.6609E-01 -2.4209E-02<_>0 -1 1908 -1.2764E-018.6579E-01 6.4206E-02<_>0 -1 1909 1.9069E-02-5.5930E-01 -1.6880E-03<_>0 -1 1910 3.2481E-024.0722E-02 4.8925E-01<_>0 -1 1911 9.4850E-03-1.9232E-01 5.1140E-01<_>0 -1 1912 5.0470E-031.8707E-01 -1.6114E-01<_>0 -1 1913 4.1268E-02-4.8818E-02 -1.1326E+00<_>0 -1 1914 -7.6359E-021.4169E+00 8.7320E-02<_>0 -1 1915 -7.2835E-021.3190E+00 -1.4819E-01<_>0 -1 1916 5.9577E-024.8377E-02 8.5612E-01<_>0 -1 1917 2.0264E-02-2.1044E-01 3.3859E-01<_>0 -1 1918 -8.0301E-02-1.2464E+00 1.1857E-01<_>0 -1 1919 -1.7835E-022.5782E-01 -2.4565E-01<_>0 -1 1920 1.1431E-022.2950E-01 -2.9498E-01<_>0 -1 1921 -2.5541E-02-8.6253E-01 -7.0400E-04<_>0 -1 1922 -7.6900E-043.1511E-01 -1.4349E-01<_>0 -1 1923 -1.4454E-022.5148E-01 -2.8233E-01<_>0 -1 1924 8.6730E-032.6601E-01 -2.8191E-01<_>197-3.2773E+00<_>0 -1 1925 5.4709E-02-5.4144E-01 6.1043E-01<_>0 -1 1926 -1.0839E-017.1740E-01 -4.1196E-01<_>0 -1 1927 2.2997E-02-5.8270E-01 2.9646E-01<_>0 -1 1928 2.7540E-03-7.4244E-01 1.4183E-01<_>0 -1 1929 -2.1520E-031.7880E-01 -6.8549E-01<_>0 -1 1930 -2.2559E-02-1.0776E+00 1.2389E-01<_>0 -1 1931 8.3025E-022.4501E-02 -1.0252E+00<_>0 -1 1932 -6.6740E-03-4.5283E-01 2.1230E-01<_>0 -1 1933 7.6485E-02-2.6973E-01 4.8580E-01<_>0 -1 1934 5.4910E-03-4.8871E-01 3.1616E-01<_>0 -1 1935 -1.0415E-024.1513E-01 -3.0045E-01<_>0 -1 1936 2.7608E-021.6204E-01 -9.9869E-01<_>0 -1 1937 -2.3272E-02-1.1024E+00 2.1125E-02<_>0 -1 1938 -5.5620E-026.5033E-01 -2.7938E-02<_>0 -1 1939 -4.0632E-024.2117E-01 -2.6764E-01<_>0 -1 1940 -7.3560E-033.5278E-01 -3.7854E-01<_>0 -1 1941 1.7007E-02-2.9190E-01 4.1054E-01<_>0 -1 1942 -3.7034E-02-1.3216E+00 1.2967E-01<_>0 -1 1943 -1.9633E-02-8.7702E-01 1.0800E-03<_>0 -1 1944 -2.3547E-022.6106E-01 -2.1481E-01<_>0 -1 1945 -4.3353E-02-9.9090E-01 -9.9560E-03<_>0 -1 1946 -2.2184E-026.3454E-01 -5.6547E-02<_>0 -1 1947 1.6531E-022.4665E-02 -7.3327E-01<_>0 -1 1948 -3.2744E-02-5.6297E-01 1.6640E-01<_>0 -1 1949 7.1416E-02-3.0000E-04 -9.3286E-01<_>0 -1 1950 8.1000E-04-9.5380E-02 2.5185E-01<_>0 -1 1951 -8.4090E-03-6.5497E-01 6.7301E-02<_>0 -1 1952 -1.7254E-02-4.6493E-01 1.6071E-01<_>0 -1 1953 -1.8641E-02-1.0594E+00 -1.9617E-02<_>0 -1 1954 -9.1980E-035.0716E-01 -1.5339E-01<_>0 -1 1955 1.8538E-02-3.0498E-01 7.3506E-01<_>0 -1 1956 -5.0335E-02-1.1140E+00 1.8000E-01<_>0 -1 1957 -2.3529E-02-8.6908E-01 -1.2460E-02<_>0 -1 1958 -2.7100E-026.5943E-01 -3.5324E-02<_>0 -1 1959 6.5880E-03-2.2953E-01 4.2425E-01<_>0 -1 1960 2.3360E-021.8356E-01 -9.8587E-01<_>0 -1 1961 1.2947E-02-3.3147E-01 2.1323E-01<_>0 -1 1962 -6.6560E-03-1.1951E-01 2.9753E-01<_>0 -1 1963 -2.2571E-023.8499E-01 -2.4434E-01<_>0 -1 1964 -6.3814E-02-8.9384E-01 1.4218E-01<_>0 -1 1965 -4.9945E-025.3864E-01 -2.0485E-01<_>0 -1 1966 6.8320E-03-5.6679E-02 3.9971E-01<_>0 -1 1967 -5.5836E-02-1.5239E+00 -5.1183E-02<_>0 -1 1968 3.1957E-017.4574E-02 1.2448E+00<_>0 -1 1969 8.0956E-02-1.9666E-01 5.9890E-01<_>0 -1 1970 -1.4912E-02-6.4021E-01 1.5808E-01<_>0 -1 1971 4.6709E-028.5239E-02 -4.5487E-01<_>0 -1 1972 6.0540E-03-4.3184E-01 2.2453E-01<_>0 -1 1973 -3.4376E-024.0203E-01 -2.3904E-01<_>0 -1 1974 -3.4924E-025.2870E-01 3.9709E-02<_>0 -1 1975 3.0030E-03-3.8754E-01 1.4193E-01<_>0 -1 1976 -1.4133E-028.7528E-01 8.5508E-02<_>0 -1 1977 -6.7940E-03-1.1649E+00 -3.3943E-02<_>0 -1 1978 -5.2886E-021.0931E+00 5.1187E-02<_>0 -1 1979 -2.1080E-031.3696E-01 -3.3850E-01<_>0 -1 1980 1.8353E-021.3662E-01 -4.0778E-01<_>0 -1 1981 1.2672E-02-1.4936E-02 -8.1708E-01<_>0 -1 1982 1.2925E-021.7625E-01 -3.2492E-01<_>0 -1 1983 -1.7921E-02-5.2745E-01 4.4443E-02<_>0 -1 1984 1.9160E-03-1.0979E-01 2.2068E-01<_>0 -1 1985 -1.4698E-023.9068E-01 -2.2225E-01<_>0 -1 1986 -1.4973E-02-2.5451E-01 1.7790E-01<_>0 -1 1987 1.4637E-02-2.5125E-02 -8.7121E-01<_>0 -1 1988 -1.0974E-027.9083E-01 2.0121E-02<_>0 -1 1989 -9.1600E-03-4.7907E-01 5.2232E-02<_>0 -1 1990 4.6180E-03-1.7245E-01 3.4528E-01<_>0 -1 1991 2.3477E-023.7760E-03 -6.5334E-01<_>0 -1 1992 3.1767E-021.6364E-02 5.8724E-01<_>0 -1 1993 -1.8420E-021.9994E-01 -3.2056E-01<_>0 -1 1994 1.9544E-021.8450E-01 -2.3794E-01<_>0 -1 1995 4.1159E-01-6.0382E-02 -1.6072E+00<_>0 -1 1996 -4.1596E-02-3.2756E-01 1.5058E-01<_>0 -1 1997 -1.0336E-02-6.2394E-01 1.3112E-02<_>0 -1 1998 1.2393E-02-3.3115E-02 5.5580E-01<_>0 -1 1999 -8.7270E-031.9883E-01 -3.7636E-01<_>0 -1 2000 1.6295E-022.0373E-01 -4.2801E-01<_>0 -1 2001 -1.0484E-02-5.6847E-01 4.4199E-02<_>0 -1 2002 -1.2432E-027.4642E-01 4.3679E-02<_>0 -1 2003 -5.0375E-028.5090E-01 -1.7774E-01<_>0 -1 2004 4.9548E-021.6785E-01 -2.9877E-01<_>0 -1 2005 -4.1085E-02-1.3303E+00 -4.9182E-02<_>0 -1 2006 1.0070E-03-6.0539E-02 1.8483E-01<_>0 -1 2007 -5.0143E-027.6448E-01 -1.8357E-01<_>0 -1 2008 -8.7880E-032.2656E-01 -6.3157E-02<_>0 -1 2009 -5.0171E-02-1.5899E+00 -6.1255E-02<_>0 -1 2010 1.0216E-011.2072E-01 -1.4120E+00<_>0 -1 2011 -1.4373E-02-1.3117E+00 -5.1936E-02<_>0 -1 2012 1.0282E-02-2.1640E-03 4.4247E-01<_>0 -1 2013 -1.1814E-026.5378E-01 -1.8724E-01<_>0 -1 2014 7.2115E-027.1847E-02 8.1496E-01<_>0 -1 2015 -1.9002E-02-6.7427E-01 -4.3200E-04<_>0 -1 2016 -4.6990E-033.3312E-01 5.5794E-02<_>0 -1 2017 -5.8157E-024.5572E-01 -2.0305E-01<_>0 -1 2018 1.1360E-03-4.4687E-02 2.2682E-01<_>0 -1 2019 -4.9415E-022.6695E-01 -2.6117E-01<_>0 -1 2020 -1.1914E-01-8.3018E-01 1.3249E-01<_>0 -1 2021 -1.8304E-02-6.7499E-01 1.7092E-02<_>0 -1 2022 -7.9200E-03-7.2287E-02 1.4426E-01<_>0 -1 2023 5.1926E-023.0922E-02 -5.5861E-01<_>0 -1 2024 6.6724E-021.3666E-01 -2.9411E-01<_>0 -1 2025 -1.3778E-02-5.9444E-01 1.5300E-02<_>0 -1 2026 -1.7761E-024.0497E-01 -3.3560E-03<_>0 -1 2027 -4.2235E-02-1.0898E+00 -4.0225E-02<_>0 -1 2028 -1.3525E-022.8922E-01 -2.5195E-01<_>0 -1 2029 -1.1106E-026.5313E-01 -1.8054E-01<_>0 -1 2030 -1.2285E-01-1.9571E+00 1.4815E-01<_>0 -1 2031 4.7716E-02-2.2876E-01 3.4234E-01<_>0 -1 2032 3.1817E-021.5976E-01 -1.0092E+00<_>0 -1 2033 4.2570E-03-3.8881E-01 8.4210E-02<_>0 -1 2034 -6.1373E-021.7153E+00 5.9325E-02<_>0 -1 2035 -2.7030E-03-3.8162E-01 8.5127E-02<_>0 -1 2036 -6.8544E-02-3.0926E+00 1.1788E-01<_>0 -1 2037 1.0373E-01-1.3769E-01 1.9009E+00<_>0 -1 2038 1.5799E-02-6.2660E-02 2.5918E-01<_>0 -1 2039 -9.8040E-03-5.6292E-01 4.3923E-02<_>0 -1 2040 -9.0230E-032.5287E-01 -4.1226E-02<_>0 -1 2041 -6.3755E-02-2.6179E+00 -7.4006E-02<_>0 -1 2042 3.8955E-025.9033E-02 8.5946E-01<_>0 -1 2043 -3.9803E-029.3600E-01 -1.5639E-01<_>0 -1 2044 5.0302E-021.3726E-01 -2.5550E+00<_>0 -1 2045 4.6250E-02-1.3964E-02 -7.1026E-01<_>0 -1 2046 6.2196E-025.9526E-02 1.6509E+00<_>0 -1 2047 -6.4776E-027.1369E-01 -1.7270E-01<_>0 -1 2048 2.7523E-021.4632E-01 -8.1429E-02<_>0 -1 2049 3.9900E-04-3.7145E-01 1.0153E-01<_>0 -1 2050 -4.3300E-03-2.3756E-01 2.6798E-01<_>0 -1 2051 4.7297E-02-2.7682E-02 -8.4910E-01<_>0 -1 2052 1.2509E-021.8730E-01 -5.6001E-01<_>0 -1 2053 4.5899E-02-1.5601E-01 9.7073E-01<_>0 -1 2054 1.9853E-011.4896E-01 -1.1016E+00<_>0 -1 2055 1.6675E-02-1.6615E-01 8.2211E-01<_>0 -1 2056 1.9830E-03-7.1250E-02 2.8811E-01<_>0 -1 2057 2.2448E-02-2.0981E-02 -7.8417E-01<_>0 -1 2058 -1.3913E-02-1.8166E-01 2.0492E-01<_>0 -1 2059 -7.7660E-03-4.5596E-01 6.3577E-02<_>0 -1 2060 -1.3209E-022.6632E-01 -1.7796E-01<_>0 -1 2061 4.9053E-02-1.5477E-01 1.1070E+00<_>0 -1 2062 2.0264E-026.8915E-02 6.9867E-01<_>0 -1 2063 -1.6828E-022.7607E-01 -2.5139E-01<_>0 -1 2064 -1.6939E-01-3.0768E+00 1.1618E-01<_>0 -1 2065 -1.1336E-01-1.4639E+00 -5.1447E-02<_>0 -1 2066 -7.7686E-028.8430E-01 4.3307E-02<_>0 -1 2067 -1.5568E-021.3672E-01 -3.4506E-01<_>0 -1 2068 -6.6019E-02-1.0300E+00 1.1601E-01<_>0 -1 2069 8.3700E-037.6429E-02 -4.4003E-01<_>0 -1 2070 3.5403E-021.1980E-01 -7.2668E-01<_>0 -1 2071 -3.9051E-026.7375E-01 -1.8196E-01<_>0 -1 2072 -9.7900E-032.1265E-01 3.6756E-02<_>0 -1 2073 -2.3047E-024.4742E-01 -2.0987E-01<_>0 -1 2074 3.1170E-033.7544E-02 2.7808E-01<_>0 -1 2075 1.3136E-02-1.9842E-01 5.4336E-01<_>0 -1 2076 1.4782E-021.3531E-01 -1.1154E-01<_>0 -1 2077 -6.0139E-028.4039E-01 -1.6712E-01<_>0 -1 2078 5.1999E-021.7372E-01 -7.8548E-01<_>0 -1 2079 2.4792E-02-1.7739E-01 6.6753E-01<_>0 -1 2080 -1.2015E-02-1.4264E-01 1.6071E-01<_>0 -1 2081 -9.8656E-021.0430E+00 -1.5770E-01<_>0 -1 2082 1.1758E-011.0956E-01 -4.4920E+00<_>0 -1 2083 -1.8923E-02-7.8543E-01 1.2984E-02<_>0 -1 2084 -2.8391E-02-6.0570E-01 1.2903E-01<_>0 -1 2085 1.3183E-02-1.4416E-02 -7.3211E-01<_>0 -1 2086 -1.1653E-01-2.0442E+00 1.4053E-01<_>0 -1 2087 -3.8880E-03-4.1862E-01 7.8705E-02<_>0 -1 2088 3.1229E-022.4633E-02 4.1870E-01<_>0 -1 2089 2.5199E-02-1.7558E-01 6.4711E-01<_>0 -1 2090 -2.8124E-02-2.2006E-01 1.4121E-01<_>0 -1 2091 3.6499E-02-6.8427E-02 -2.3411E+00<_>0 -1 2092 -7.2293E-021.2899E+00 8.4875E-02<_>0 -1 2093 -4.1671E-02-1.1631E+00 -5.3753E-02<_>0 -1 2094 4.7703E-027.0101E-02 7.3677E-01<_>0 -1 2095 6.5793E-02-1.7755E-01 6.9780E-01<_>0 -1 2096 1.3905E-022.1937E-01 -2.0391E-01<_>0 -1 2097 -2.7731E-026.1868E-01 -1.7804E-01<_>0 -1 2098 -1.5880E-02-4.6484E-01 1.8829E-01<_>0 -1 2099 7.4128E-02-1.2858E-01 3.2792E+00<_>0 -1 2100 -8.9000E-04-3.0118E-01 2.3819E-01<_>0 -1 2101 1.7965E-02-2.2285E-01 2.9954E-01<_>0 -1 2102 -2.5380E-032.5064E-01 -1.3666E-01<_>0 -1 2103 -9.0680E-032.9017E-01 -2.8930E-01<_>0 -1 2104 4.9170E-021.9156E-01 -6.8329E-01<_>0 -1 2105 -3.0681E-02-7.5677E-01 -1.3280E-02<_>0 -1 2106 1.0017E-018.4454E-02 1.0889E+00<_>0 -1 2107 3.1950E-03-2.6919E-01 1.9538E-01<_>0 -1 2108 3.5503E-021.3632E-01 -5.6917E-01<_>0 -1 2109 4.5900E-04-4.0444E-01 1.4075E-01<_>0 -1 2110 2.5259E-021.6243E-01 -5.5742E-01<_>0 -1 2111 -5.1550E-033.1133E-01 -2.2756E-01<_>0 -1 2112 1.5870E-03-2.6868E-01 1.9565E-01<_>0 -1 2113 -1.6205E-021.5486E-01 -3.4058E-01<_>0 -1 2114 -2.9624E-021.1467E+00 9.0558E-02<_>0 -1 2115 -1.5930E-03-7.1258E-01 -7.0400E-04<_>0 -1 2116 -5.4019E-024.1537E-01 2.7246E-02<_>0 -1 2117 -6.6211E-02-1.3340E+00 -4.7353E-02<_>0 -1 2118 2.7941E-021.4446E-01 -5.1518E-01<_>0 -1 2119 2.8957E-02-4.9966E-02 -1.1929E+00<_>0 -1 2120 -2.0425E-026.3881E-01 3.8141E-02<_>0 -1 2121 1.2417E-02-2.1547E-01 4.9478E-01<_>181-3.3196E+00<_>0 -1 2122 4.3274E-02-8.0494E-01 3.9897E-01<_>0 -1 2123 1.8616E-01-3.1655E-01 6.8877E-01<_>0 -1 2124 3.1861E-02-6.4266E-01 2.5551E-01<_>0 -1 2125 1.4022E-02-4.5927E-01 3.1171E-01<_>0 -1 2126 -6.3030E-034.6027E-01 -2.7439E-01<_>0 -1 2127 -5.4310E-033.6609E-01 -2.7206E-01<_>0 -1 2128 1.6823E-022.3477E-02 -8.8444E-01<_>0 -1 2129 2.6039E-021.7489E-01 -5.4565E-01<_>0 -1 2130 -2.6720E-02-9.6396E-01 2.3525E-02<_>0 -1 2131 -1.7042E-02-7.0849E-01 2.1468E-01<_>0 -1 2132 5.9570E-037.3601E-02 -6.8226E-01<_>0 -1 2133 -2.8680E-03-7.4935E-01 2.3803E-01<_>0 -1 2134 -4.3775E-026.8323E-01 -2.1380E-01<_>0 -1 2135 5.1633E-02-1.2566E-01 6.7524E-01<_>0 -1 2136 8.1780E-037.0690E-02 -8.0666E-01<_>0 -1 2137 -5.2842E-029.5434E-01 1.6548E-02<_>0 -1 2138 5.2584E-02-2.8414E-01 4.7130E-01<_>0 -1 2139 -1.2659E-023.8445E-01 -6.2288E-02<_>0 -1 2140 1.1694E-025.6000E-05 -1.0173E+00<_>0 -1 2141 -2.3919E-028.4921E-01 5.7400E-03<_>0 -1 2142 -6.1674E-02-9.2571E-01 -1.7680E-03<_>0 -1 2143 -1.8280E-03-5.4372E-01 2.4932E-01<_>0 -1 2144 3.5258E-02-7.3720E-03 -9.3964E-01<_>0 -1 2145 -1.8438E-027.2137E-01 1.0492E-02<_>0 -1 2146 -3.8389E-021.9273E-01 -3.5832E-01<_>0 -1 2147 9.9721E-021.1354E-01 -1.6304E+00<_>0 -1 2148 8.4462E-02-5.3421E-02 -1.6981E+00<_>0 -1 2149 4.0270E-02-1.0783E-01 5.1927E-01<_>0 -1 2150 5.8936E-02-1.8054E-01 9.5120E-01<_>0 -1 2151 1.4957E-011.6785E-01 -1.1592E+00<_>0 -1 2152 6.9400E-042.0491E-01 -3.3118E-01<_>0 -1 2153 -3.3369E-029.3468E-01 -2.9640E-03<_>0 -1 2154 9.3760E-033.7000E-03 -7.7550E-01<_>0 -1 2155 4.3194E-02-2.2040E-03 7.4590E-01<_>0 -1 2156 -6.7555E-027.2292E-01 -1.8404E-01<_>0 -1 2157 -3.1169E-011.0014E+00 3.4003E-02<_>0 -1 2158 2.9744E-02-4.6356E-02 -1.2782E+00<_>0 -1 2159 1.0737E-021.4812E-02 6.6650E-01<_>0 -1 2160 -2.8841E-02-9.4223E-01 -2.0797E-02<_>0 -1 2161 -5.7650E-03-4.3542E-01 2.3386E-01<_>0 -1 2162 2.8411E-02-1.7616E-01 8.5765E-01<_>0 -1 2163 -2.9008E-025.7978E-01 2.8566E-02<_>0 -1 2164 2.4966E-02-2.2729E-02 -9.6773E-01<_>0 -1 2165 1.2036E-02-1.4215E-01 5.1688E-01<_>0 -1 2166 -4.2514E-029.7274E-01 -1.8120E-01<_>0 -1 2167 1.0276E-02-8.3100E-02 3.1763E-01<_>0 -1 2168 -6.9192E-02-2.0669E+00 -6.0174E-02<_>0 -1 2169 -4.6770E-034.4132E-01 2.3209E-02<_>0 -1 2170 -1.3924E-022.8607E-01 -2.9153E-01<_>0 -1 2171 -1.5334E-02-5.7415E-01 2.3063E-01<_>0 -1 2172 -1.0239E-023.4479E-01 -2.6080E-01<_>0 -1 2173 -5.0989E-025.6154E-01 6.1219E-02<_>0 -1 2174 3.0690E-02-1.4773E-01 1.6378E+00<_>0 -1 2175 -1.1224E-022.4006E-01 -4.4865E-01<_>0 -1 2176 -6.2900E-034.3119E-01 -2.3809E-01<_>0 -1 2177 7.8591E-021.9865E-02 8.0854E-01<_>0 -1 2178 -1.0179E-021.8193E-01 -3.2878E-01<_>0 -1 2179 3.1227E-021.4974E-01 -1.4180E+00<_>0 -1 2180 4.0197E-02-1.9760E-01 5.8508E-01<_>0 -1 2181 1.6138E-025.0000E-04 3.9050E-01<_>0 -1 2182 -4.5519E-021.2647E+00 -1.5633E-01<_>0 -1 2183 -1.8130E-026.5149E-01 1.0236E-02<_>0 -1 2184 -1.4002E-02-1.0345E+00 -3.2183E-02<_>0 -1 2185 -3.8816E-02-4.7874E-01 1.6291E-01<_>0 -1 2186 3.1656E-02-2.0983E-01 5.4576E-01<_>0 -1 2187 -1.0840E-025.1899E-01 -1.5080E-02<_>0 -1 2188 1.2033E-02-2.1108E-01 7.5937E-01<_>0 -1 2189 7.0773E-021.8049E-01 -7.4049E-01<_>0 -1 2190 5.3140E-01-1.4492E-01 1.5360E+00<_>0 -1 2191 -1.4774E-02-2.8154E-01 2.0407E-01<_>0 -1 2192 -2.2410E-03-4.4876E-01 5.3989E-02<_>0 -1 2193 4.9968E-024.1514E-02 2.9417E-01<_>0 -1 2194 -4.7702E-023.9674E-01 -2.8302E-01<_>0 -1 2195 -9.1311E-022.1994E+00 8.7965E-02<_>0 -1 2196 3.8070E-02-2.8026E-01 2.5156E-01<_>0 -1 2197 -1.5539E-023.4157E-01 1.7925E-02<_>0 -1 2198 -1.5446E-022.8680E-01 -2.5136E-01<_>0 -1 2199 -5.7388E-026.3830E-01 8.8598E-02<_>0 -1 2200 -5.9440E-037.9017E-02 -4.0775E-01<_>0 -1 2201 -6.9969E-02-4.4644E-01 1.7220E-01<_>0 -1 2202 -2.5065E-02-9.8270E-01 -3.5388E-02<_>0 -1 2203 1.7216E-022.2706E-01 -8.0550E-01<_>0 -1 2204 -4.4279E-028.3952E-01 -1.7430E-01<_>0 -1 2205 4.3989E-021.1557E-01 -1.9667E+00<_>0 -1 2206 1.5907E-02-3.7576E-02 -1.0311E+00<_>0 -1 2207 -9.2755E-02-1.3530E+00 1.2141E-01<_>0 -1 2208 7.1037E-02-1.7684E-01 7.4485E-01<_>0 -1 2209 5.7762E-021.2836E-01 -4.4444E-01<_>0 -1 2210 -1.6432E-028.0153E-01 -1.7492E-01<_>0 -1 2211 2.3939E-021.6145E-01 -1.2365E-01<_>0 -1 2212 1.2636E-021.5412E-01 -3.3294E-01<_>0 -1 2213 -5.4348E-02-1.8401E+00 1.4836E-01<_>0 -1 2214 -1.3262E-02-8.0839E-01 -2.7726E-02<_>0 -1 2215 6.1340E-03-1.3785E-01 3.2858E-01<_>0 -1 2216 2.8991E-02-2.5517E-02 -8.3387E-01<_>0 -1 2217 -2.1986E-02-7.3740E-01 1.7887E-01<_>0 -1 2218 5.3270E-03-4.5449E-01 6.8791E-02<_>0 -1 2219 8.6048E-022.1009E-01 -3.7809E-01<_>0 -1 2220 -8.5550E-034.0135E-01 -2.1074E-01<_>0 -1 2221 6.7790E-03-2.1649E-02 4.5421E-01<_>0 -1 2222 -6.3960E-03-4.9819E-01 7.5908E-02<_>0 -1 2223 8.9470E-031.7858E-01 -2.8455E-01<_>0 -1 2224 3.2590E-034.6625E-02 -5.5206E-01<_>0 -1 2225 4.1477E-021.7550E-01 -2.0704E-01<_>0 -1 2226 -6.7450E-03-4.6393E-01 6.9304E-02<_>0 -1 2227 3.0565E-025.1735E-02 7.5551E-01<_>0 -1 2228 -7.4780E-031.4894E-01 -3.1907E-01<_>0 -1 2229 8.9089E-021.3739E-01 -1.1380E+00<_>0 -1 2230 7.3230E-03-2.8829E-01 1.9089E-01<_>0 -1 2231 -1.8205E-02-3.0179E-01 1.6796E-01<_>0 -1 2232 -2.5828E-02-9.8138E-01 -1.9861E-02<_>0 -1 2233 1.0936E-014.8790E-02 5.3118E-01<_>0 -1 2234 -1.1425E-022.3706E-01 -2.7925E-01<_>0 -1 2235 -5.7566E-024.7255E-01 6.5171E-02<_>0 -1 2236 1.0278E-01-2.0765E-01 5.0948E-01<_>0 -1 2237 2.7042E-021.6421E-01 -1.4509E+00<_>0 -1 2238 -1.3635E-02-5.6544E-01 2.3789E-02<_>0 -1 2239 -3.2158E-01-3.5603E+00 1.1801E-01<_>0 -1 2240 2.0458E-01-3.7016E-02 -1.0225E+00<_>0 -1 2241 -7.0347E-02-5.6492E-01 1.8525E-01<_>0 -1 2242 3.7831E-02-2.9902E-02 -8.2921E-01<_>0 -1 2243 -7.0298E-02-5.3172E-01 1.4430E-01<_>0 -1 2244 6.3221E-02-2.2041E-01 4.7952E-01<_>0 -1 2245 3.6393E-021.4223E-01 -6.1194E-01<_>0 -1 2246 4.0100E-03-3.4561E-01 1.1739E-01<_>0 -1 2247 -4.9106E-029.5984E-01 6.4935E-02<_>0 -1 2248 -7.1583E-021.7386E+00 -1.4253E-01<_>0 -1 2249 -3.8009E-021.3873E+00 6.6188E-02<_>0 -1 2250 -3.1570E-035.3677E-02 -5.4048E-01<_>0 -1 2251 1.9459E-02-9.3620E-02 3.9131E-01<_>0 -1 2252 1.1294E-023.7224E-02 -5.4252E-01<_>0 -1 2253 -3.3495E-029.5308E-01 3.7697E-02<_>0 -1 2254 9.2035E-02-1.3488E-01 2.2897E+00<_>0 -1 2255 3.7530E-032.2824E-01 -5.9984E-01<_>0 -1 2256 1.2848E-02-2.2005E-01 3.7222E-01<_>0 -1 2257 -1.4316E-011.2856E+00 4.7237E-02<_>0 -1 2258 -9.6880E-02-3.9551E+00 -7.2904E-02<_>0 -1 2259 -8.8460E-033.7675E-01 -4.6484E-02<_>0 -1 2260 1.5900E-02-2.4457E-02 -8.0035E-01<_>0 -1 2261 7.0372E-021.7019E-01 -6.3069E-01<_>0 -1 2262 -3.7954E-02-9.3667E-01 -4.1214E-02<_>0 -1 2263 5.1598E-011.3081E-01 -1.5802E+00<_>0 -1 2264 -3.2843E-02-1.1442E+00 -4.9174E-02<_>0 -1 2265 -3.6357E-024.9606E-01 -3.4459E-02<_>0 -1 2266 6.8080E-03-3.0998E-01 1.7055E-01<_>0 -1 2267 -1.6114E-02-3.7905E-01 1.6079E-01<_>0 -1 2268 8.4530E-03-1.8655E-01 5.6368E-01<_>0 -1 2269 -1.3752E-01-5.8990E-01 1.1750E-01<_>0 -1 2270 1.7688E-01-1.5425E-01 9.2911E-01<_>0 -1 2271 7.9310E-033.2191E-01 -1.6393E-01<_>0 -1 2272 1.0972E-01-1.5877E-01 1.0186E+00<_>0 -1 2273 -3.0293E-027.5587E-01 3.1795E-02<_>0 -1 2274 -2.3118E-02-8.8451E-01 -9.5040E-03<_>0 -1 2275 -3.0900E-032.3838E-01 -1.1606E-01<_>0 -1 2276 -3.3392E-02-1.8738E+00 -6.8503E-02<_>0 -1 2277 1.3190E-021.2920E-01 -6.7512E-01<_>0 -1 2278 1.4661E-02-2.4829E-02 -7.4397E-01<_>0 -1 2279 -1.3248E-024.6820E-01 -2.4165E-02<_>0 -1 2280 -1.6219E-024.0084E-01 -2.1256E-01<_>0 -1 2281 -2.9052E-02-1.5650E+00 1.4376E-01<_>0 -1 2282 -1.0153E-01-1.9221E+00 -6.9560E-02<_>0 -1 2283 3.7754E-021.3397E-01 -2.2639E+00<_>0 -1 2284 -2.8556E-011.0215E+00 -1.5232E-01<_>0 -1 2285 1.5361E-01-9.7409E-02 4.1662E-01<_>0 -1 2286 -2.1200E-041.1272E-01 -4.1654E-01<_>0 -1 2287 -2.0598E-026.0540E-01 6.2468E-02<_>0 -1 2288 3.7354E-02-1.8919E-01 4.6465E-01<_>0 -1 2289 5.7275E-021.1565E-01 -1.3213E+00<_>0 -1 2290 5.1030E-03-2.8062E-01 1.9313E-01<_>0 -1 2291 -5.4645E-027.2429E-01 7.5448E-02<_>0 -1 2292 2.5349E-02-1.9482E-01 4.6033E-01<_>0 -1 2293 2.4311E-021.5564E-01 -4.9914E-01<_>0 -1 2294 3.5962E-02-5.8573E-02 -1.5418E+00<_>0 -1 2295 -1.0001E-01-1.6100E+00 1.1451E-01<_>0 -1 2296 8.4436E-02-6.1407E-02 -1.4673E+00<_>0 -1 2297 1.5948E-021.6288E-01 -1.1026E-01<_>0 -1 2298 3.3824E-02-1.7933E-01 5.7218E-01<_>0 -1 2299 -6.1996E-024.6512E+00 9.4534E-02<_>0 -1 2300 6.9877E-02-1.6986E-01 8.7029E-01<_>0 -1 2301 -2.7917E-029.1043E-01 5.6827E-02<_>0 -1 2302 -1.2764E-022.2067E-01 -2.7769E-01<_>199-3.2573E+00<_>0 -1 2303 2.1662E-02-8.9869E-01 2.9436E-01<_>0 -1 2304 1.0045E-01-3.7659E-01 6.0891E-01<_>0 -1 2305 2.6004E-02-3.8129E-01 3.9217E-01<_>0 -1 2306 2.8441E-02-1.8182E-01 5.8927E-01<_>0 -1 2307 3.8612E-02-2.2400E-01 6.3780E-01<_>0 -1 2308 -4.6595E-027.0812E-01 -1.4666E-01<_>0 -1 2309 -4.2792E-024.7680E-01 -2.9233E-01<_>0 -1 2310 3.7960E-03-1.8510E-01 5.2627E-01<_>0 -1 2311 4.2349E-023.9245E-02 -8.9198E-01<_>0 -1 2312 1.9599E-02-2.3358E-01 4.4146E-01<_>0 -1 2313 8.7400E-04-4.6064E-01 1.7690E-01<_>0 -1 2314 -4.3630E-033.3493E-01 -2.9893E-01<_>0 -1 2315 1.6973E-02-1.6409E-01 1.5994E+00<_>0 -1 2316 3.6064E-022.2602E-01 -5.3186E-01<_>0 -1 2317 -7.0865E-021.5221E-01 -4.1915E-01<_>0 -1 2318 -6.3076E-02-1.4874E+00 1.2954E-01<_>0 -1 2319 2.9670E-02-1.9146E-01 9.8185E-01<_>0 -1 2320 3.7874E-021.3460E-01 -5.6316E-01<_>0 -1 2321 -3.3289E-02-1.0828E+00 -1.1504E-02<_>0 -1 2322 -3.1609E-02-5.9224E-01 1.3395E-01<_>0 -1 2323 1.0740E-03-4.9186E-01 9.4446E-02<_>0 -1 2324 -7.1556E-025.9710E-01 -3.9553E-02<_>0 -1 2325 -8.1170E-02-1.1818E+00 -2.8254E-02<_>0 -1 2326 4.4860E-03-6.1028E-01 2.2619E-01<_>0 -1 2327 -4.2176E-02-1.1436E+00 -2.9002E-02<_>0 -1 2328 -6.5640E-02-1.6470E+00 1.2810E-01<_>0 -1 2329 1.8189E-02-3.1149E-01 2.5740E-01<_>0 -1 2330 -5.1520E-02-6.9207E-01 1.5271E-01<_>0 -1 2331 -4.7151E-02-7.1868E-01 2.6880E-03<_>0 -1 2332 1.7489E-022.2371E-01 -5.5382E-01<_>0 -1 2333 -2.5264E-021.0320E+00 -1.7496E-01<_>0 -1 2334 -4.0745E-024.4962E-01 3.9349E-02<_>0 -1 2335 -3.7667E-02-8.5476E-01 -1.2464E-02<_>0 -1 2336 -1.3411E-025.7846E-01 -1.7468E-02<_>0 -1 2337 -7.9000E-05-3.7749E-01 1.3962E-01<_>0 -1 2338 -1.1415E-02-2.6187E-01 2.3712E-01<_>0 -1 2339 3.7200E-02-2.8626E-02 -1.2945E+00<_>0 -1 2340 3.4050E-032.0531E-01 -1.8747E-01<_>0 -1 2341 -2.2483E-026.7027E-01 -1.9594E-01<_>0 -1 2342 2.3275E-021.7405E-01 -3.2746E-01<_>0 -1 2343 -1.3917E-02-8.3954E-01 -6.3760E-03<_>0 -1 2344 7.5430E-03-3.4195E-02 5.8998E-01<_>0 -1 2345 -1.1539E-024.2143E-01 -2.3510E-01<_>0 -1 2346 5.2502E-026.9304E-02 7.3226E-01<_>0 -1 2347 5.2716E-02-1.5688E-01 1.0907E+00<_>0 -1 2348 -1.1726E-02-7.0934E-01 1.6829E-01<_>0 -1 2349 9.5946E-02-1.6193E-01 1.0073E+00<_>0 -1 2350 -1.5872E-023.9008E-01 -5.3777E-02<_>0 -1 2351 3.4818E-021.7180E-02 -9.3942E-01<_>0 -1 2352 3.4792E-025.0463E-02 5.4466E-01<_>0 -1 2353 1.6284E-02-2.6981E-01 4.0365E-01<_>0 -1 2354 -4.4319E-028.4400E-01 3.2883E-02<_>0 -1 2355 -5.5690E-031.5309E-01 -3.4960E-01<_>0 -1 2356 -6.5842E-02-9.2711E-01 1.6801E-01<_>0 -1 2357 -7.3337E-025.1614E-01 -2.0236E-01<_>0 -1 2358 1.6450E-021.3951E-01 -4.9301E-01<_>0 -1 2359 -9.2630E-03-9.0102E-01 -1.6116E-02<_>0 -1 2360 5.9140E-031.9858E-01 -1.6731E-01<_>0 -1 2361 -8.4700E-049.4005E-02 -4.1571E-01<_>0 -1 2362 2.0533E-01-6.0022E-02 7.0994E-01<_>0 -1 2363 -1.6883E-022.4392E-01 -3.0552E-01<_>0 -1 2364 -1.9111E-026.1230E-01 2.4253E-02<_>0 -1 2365 -2.5963E-029.0765E-01 -1.6722E-01<_>0 -1 2366 -2.1762E-02-3.1385E-01 2.0135E-01<_>0 -1 2367 -2.4120E-02-6.6588E-01 7.4560E-03<_>0 -1 2368 4.7130E-025.9534E-02 8.7805E-01<_>0 -1 2369 -4.5985E-028.0068E-01 -1.7252E-01<_>0 -1 2370 2.6508E-021.8774E-01 -6.0851E-01<_>0 -1 2371 -4.8615E-025.8644E-01 -1.9428E-01<_>0 -1 2372 -1.8562E-02-2.5588E-01 1.6326E-01<_>0 -1 2373 1.2678E-02-1.4228E-02 -7.6738E-01<_>0 -1 2374 -1.1920E-032.0495E-01 -1.1404E-01<_>0 -1 2375 -4.9089E-02-1.0741E+00 -3.8941E-02<_>0 -1 2376 -1.7437E-02-5.7974E-01 1.8585E-01<_>0 -1 2377 -1.4770E-02-6.6150E-01 5.3120E-03<_>0 -1 2378 -2.2905E-01-4.8305E-01 1.2326E-01<_>0 -1 2379 -1.2707E-015.7453E-01 -1.9420E-01<_>0 -1 2380 1.0339E-02-5.4642E-02 2.4502E-01<_>0 -1 2381 6.9010E-031.2181E-01 -3.8797E-01<_>0 -1 2382 2.9025E-011.0966E-01 -30.<_>0 -1 2383 -2.3805E-01-1.7353E+00 -6.3810E-02<_>0 -1 2384 6.2481E-021.3523E-01 -7.0301E-01<_>0 -1 2385 4.7110E-03-4.6984E-01 6.0342E-02<_>0 -1 2386 -2.7816E-026.9808E-01 1.3720E-03<_>0 -1 2387 -1.7020E-021.6870E+00 -1.4315E-01<_>0 -1 2388 -4.9755E-027.9498E-01 7.7200E-04<_>0 -1 2389 -7.4733E-02-1.0132E+00 -1.9389E-02<_>0 -1 2390 3.2009E-021.4412E-01 -4.2139E-01<_>0 -1 2391 -9.4464E-025.0683E-01 -2.0479E-01<_>0 -1 2392 -1.5427E-02-1.5811E-01 1.7807E-01<_>0 -1 2393 -4.0540E-03-5.4367E-01 3.1235E-02<_>0 -1 2394 3.0080E-03-1.7377E-01 3.0442E-01<_>0 -1 2395 -1.0092E-022.5104E-01 -2.6224E-01<_>0 -1 2396 -3.8818E-029.3227E-01 7.2660E-02<_>0 -1 2397 3.4652E-02-3.3935E-02 -8.5708E-01<_>0 -1 2398 -4.6730E-033.4969E-01 -4.8518E-02<_>0 -1 2399 6.8500E-046.6573E-02 -4.4974E-01<_>0 -1 2400 3.5317E-021.4276E-01 -4.6726E-01<_>0 -1 2401 -2.3570E-02-1.0286E+00 -4.5288E-02<_>0 -1 2402 -1.9110E-03-1.9652E-01 2.8661E-01<_>0 -1 2403 -1.6659E-02-7.7532E-01 -8.3280E-03<_>0 -1 2404 6.6062E-011.3232E-01 -3.5267E+00<_>0 -1 2405 1.0971E-01-1.5547E-01 1.4674E+00<_>0 -1 2406 1.3501E-021.5233E-01 -1.3021E+00<_>0 -1 2407 -2.2872E-02-7.1326E-01 -8.7040E-03<_>0 -1 2408 -8.1821E-021.1128E+00 8.3220E-02<_>0 -1 2409 -5.2728E-029.3165E-01 -1.7104E-01<_>0 -1 2410 -2.5242E-02-1.9734E-01 2.5359E-01<_>0 -1 2411 -4.3819E-024.1815E-01 -2.4586E-01<_>0 -1 2412 -1.8189E-02-5.1743E-01 2.0174E-01<_>0 -1 2413 2.3466E-02-4.3071E-02 -1.0637E+00<_>0 -1 2414 3.4216E-025.3781E-02 4.9707E-01<_>0 -1 2415 2.5693E-02-2.3800E-01 4.1651E-01<_>0 -1 2416 -2.6565E-02-8.8575E-01 1.3366E-01<_>0 -1 2417 6.0942E-02-2.0670E-01 5.8309E-01<_>0 -1 2418 1.4475E-011.3282E-01 -3.1449E+00<_>0 -1 2419 5.3411E-02-1.7325E-01 6.9191E-01<_>0 -1 2420 1.1408E-025.4822E-02 3.0240E-01<_>0 -1 2421 -2.3180E-031.5821E-01 -3.1973E-01<_>0 -1 2422 -2.9695E-027.1275E-01 5.8136E-02<_>0 -1 2423 2.7250E-02-1.5754E-01 9.2144E-01<_>0 -1 2424 -3.6200E-03-3.4548E-01 2.0221E-01<_>0 -1 2425 -1.2579E-02-5.5650E-01 2.0389E-02<_>0 -1 2426 -8.8849E-02-3.6100E+00 1.3164E-01<_>0 -1 2427 -1.9257E-025.1909E-01 -1.9284E-01<_>0 -1 2428 -1.6667E-02-8.7500E-02 1.5812E-01<_>0 -1 2429 1.2932E-022.7406E-02 -5.5124E-01<_>0 -1 2430 -1.3432E-022.3458E-01 -4.3235E-02<_>0 -1 2431 1.8810E-02-3.9681E-02 -9.4373E-01<_>0 -1 2432 -6.4350E-034.5704E-01 -4.0520E-03<_>0 -1 2433 -2.4249E-02-7.6248E-01 -1.9857E-02<_>0 -1 2434 -2.9668E-02-3.7413E+00 1.1251E-01<_>0 -1 2435 5.1150E-03-6.3782E-01 1.1224E-02<_>0 -1 2436 -5.7820E-031.9374E-01 -8.2042E-02<_>0 -1 2437 1.6607E-02-1.6192E-01 1.1335E+00<_>0 -1 2438 3.8228E-022.1105E-02 7.6264E-01<_>0 -1 2439 -5.7094E-02-1.6975E+00 -5.9762E-02<_>0 -1 2440 -5.3883E-021.1850E+00 9.0967E-02<_>0 -1 2441 -2.6110E-03-4.0941E-01 8.3821E-02<_>0 -1 2442 2.9714E-011.5530E-01 -1.0995E+00<_>0 -1 2443 -8.9063E-024.8947E-01 -2.0041E-01<_>0 -1 2444 -5.6193E-02-2.4581E-01 1.4366E-01<_>0 -1 2445 3.7005E-02-4.8169E-02 -1.2311E+00<_>0 -1 2446 -8.4840E-034.3373E-01 1.3780E-02<_>0 -1 2447 -2.4380E-031.8950E-01 -3.2294E-01<_>0 -1 2448 -7.1640E-02-4.3979E-01 2.2730E-01<_>0 -1 2449 5.2260E-03-2.0548E-01 5.0933E-01<_>0 -1 2450 -6.1360E-033.1157E-01 7.0681E-02<_>0 -1 2451 1.5595E-02-3.0935E-01 1.5628E-01<_>0 -1 2452 2.5996E-021.3822E-01 -1.7617E-01<_>0 -1 2453 -1.2085E-02-5.1070E-01 5.8441E-02<_>0 -1 2454 -6.7836E-024.7757E-01 -7.1446E-02<_>0 -1 2455 -1.4715E-024.5239E-01 -1.9861E-01<_>0 -1 2456 2.5119E-021.2955E-01 -8.6266E-01<_>0 -1 2457 1.8826E-02-4.1570E-02 -1.1355E+00<_>0 -1 2458 -2.1264E-02-3.4738E-01 1.5779E-01<_>0 -1 2459 9.4610E-034.8640E-03 -6.1655E-01<_>0 -1 2460 2.2958E-018.1373E-02 6.9841E-01<_>0 -1 2461 -3.8062E-021.1616E+00 -1.4977E-01<_>0 -1 2462 -1.3485E-02-3.2036E-01 1.7365E-01<_>0 -1 2463 3.6239E-02-1.8158E-01 6.1957E-01<_>0 -1 2464 6.7210E-037.9600E-04 4.2441E-01<_>0 -1 2465 9.6526E-02-1.4697E-01 1.2526E+00<_>0 -1 2466 -3.5657E-02-3.9782E-01 1.4191E-01<_>0 -1 2467 1.0772E-02-1.8194E-01 5.9762E-01<_>0 -1 2468 7.9280E-021.4642E-01 -7.8837E-01<_>0 -1 2469 3.2841E-02-6.2408E-02 -1.4227E+00<_>0 -1 2470 -2.7781E-023.4033E-01 3.0670E-02<_>0 -1 2471 -4.0340E-033.1085E-01 -2.2596E-01<_>0 -1 2472 7.4260E-03-3.8937E-02 3.1702E-01<_>0 -1 2473 1.1214E-01-1.7578E-01 6.5057E-01<_>0 -1 2474 -1.1878E-01-1.0093E+00 1.1070E-01<_>0 -1 2475 -4.1585E-02-5.3806E-01 1.9905E-02<_>0 -1 2476 -2.7966E-024.8143E-01 3.3591E-02<_>0 -1 2477 -1.2506E-012.6352E-01 -2.5738E-01<_>0 -1 2478 2.3667E-013.6508E-02 9.0656E-01<_>0 -1 2479 -2.9476E-02-6.0049E-01 9.5880E-03<_>0 -1 2480 3.7793E-021.5506E-01 -9.5733E-01<_>0 -1 2481 7.2044E-02-1.4526E-01 1.3677E+00<_>0 -1 2482 9.7760E-031.2916E-02 2.1641E-01<_>0 -1 2483 5.2154E-02-1.6360E-02 -8.8356E-01<_>0 -1 2484 -4.3791E-023.5830E-01 6.5131E-02<_>0 -1 2485 -3.8379E-021.1961E+00 -1.4972E-01<_>0 -1 2486 -9.8839E-02-6.1834E-01 1.2786E-01<_>0 -1 2487 -1.2191E-01-1.8276E+00 -6.4863E-02<_>0 -1 2488 -1.1982E-01-30. 1.1323E-01<_>0 -1 2489 3.0910E-02-2.3934E-01 3.6333E-01<_>0 -1 2490 1.0801E-02-3.5140E-02 2.7708E-01<_>0 -1 2491 5.6845E-02-1.5524E-01 1.0803E+00<_>0 -1 2492 1.0280E-03-6.1203E-02 2.0508E-01<_>0 -1 2493 -2.8274E-02-6.4778E-01 2.3917E-02<_>0 -1 2494 -1.6014E-011.0892E+00 5.8389E-02<_>0 -1 2495 4.9630E-03-2.5806E-01 2.0835E-01<_>0 -1 2496 4.6937E-021.3886E-01 -1.5663E+00<_>0 -1 2497 2.4286E-02-2.0728E-01 5.2431E-01<_>0 -1 2498 7.0202E-021.4797E-01 -1.3095E+00<_>0 -1 2499 9.8120E-032.7906E-02 -5.0865E-01<_>0 -1 2500 -5.6201E-021.2618E+00 6.3802E-02<_>0 -1 2501 1.0983E-01-1.2850E-01 3.0776E+00<_>211-3.3703E+00<_>0 -1 2502 2.0910E-02-6.8559E-01 3.8984E-01<_>0 -1 2503 3.5032E-02-4.7724E-01 4.5027E-01<_>0 -1 2504 3.9799E-02-4.7011E-01 4.2702E-01<_>0 -1 2505 -4.8410E-032.5614E-01 -6.6556E-01<_>0 -1 2506 2.3440E-03-4.8083E-01 2.8014E-01<_>0 -1 2507 2.5313E-02-2.3948E-01 4.4192E-01<_>0 -1 2508 -3.2193E-027.6087E-01 -2.5059E-01<_>0 -1 2509 7.5409E-02-3.4975E-01 3.4380E-01<_>0 -1 2510 -1.8469E-02-7.9086E-01 3.4788E-02<_>0 -1 2511 -1.2802E-024.7108E-01 -6.0006E-02<_>0 -1 2512 -2.6598E-026.7116E-01 -2.4258E-01<_>0 -1 2513 2.1989E-022.4717E-01 -4.8302E-01<_>0 -1 2514 1.4654E-01-2.1504E-01 7.2056E-01<_>0 -1 2515 3.5310E-032.7931E-01 -3.4340E-01<_>0 -1 2516 9.4010E-035.5862E-02 -8.2144E-01<_>0 -1 2517 -8.6390E-03-9.9621E-01 1.8875E-01<_>0 -1 2518 -3.9193E-02-1.1946E+00 -2.9198E-02<_>0 -1 2519 2.4855E-021.4988E-01 -5.4138E-01<_>0 -1 2520 -3.4995E-02-1.4210E+00 -4.2314E-02<_>0 -1 2521 -1.8379E-02-2.8243E-01 1.5582E-01<_>0 -1 2522 -1.3592E-024.7317E-01 -2.1937E-01<_>0 -1 2523 6.2630E-03-5.9714E-02 6.0626E-01<_>0 -1 2524 -1.8478E-02-8.5647E-01 -1.3784E-02<_>0 -1 2525 1.4236E-021.6655E-01 -2.7714E-01<_>0 -1 2526 -3.2547E-02-1.1728E+00 -4.0185E-02<_>0 -1 2527 -2.6410E-032.6514E-01 -5.6343E-02<_>0 -1 2528 -8.7800E-043.6556E-02 -5.5075E-01<_>0 -1 2529 4.7372E-02-4.2614E-02 4.8195E-01<_>0 -1 2530 -7.0790E-032.8699E-01 -3.2923E-01<_>0 -1 2531 -4.3146E-02-1.4065E+00 1.2836E-01<_>0 -1 2532 2.0592E-02-2.1435E-01 5.3982E-01<_>0 -1 2533 -2.2367E-023.3718E-01 4.5212E-02<_>0 -1 2534 5.0040E-02-2.5122E-01 4.1750E-01<_>0 -1 2535 6.1795E-024.0085E-02 6.8780E-01<_>0 -1 2536 -4.1862E-025.3027E-01 -2.2902E-01<_>0 -1 2537 -3.1960E-032.5161E-01 -2.1515E-01<_>0 -1 2538 2.4255E-027.2320E-03 -7.2519E-01<_>0 -1 2539 -1.7304E-02-4.9958E-01 1.8395E-01<_>0 -1 2540 -4.1470E-038.5212E-02 -4.6365E-01<_>0 -1 2541 -1.4370E-02-5.2259E-01 2.3893E-01<_>0 -1 2542 -9.0400E-03-6.3250E-01 3.2551E-02<_>0 -1 2543 -1.2373E-011.2856E+00 7.6545E-02<_>0 -1 2544 -8.2222E-028.3208E-01 -1.8591E-01<_>0 -1 2545 6.5659E-021.1299E-01 -30.<_>0 -1 2546 -3.1583E-02-1.3486E+00 -4.7097E-02<_>0 -1 2547 -7.9636E-02-1.3534E+00 1.5669E-01<_>0 -1 2548 -1.8880E-024.0300E-01 -2.5149E-01<_>0 -1 2549 -5.0150E-03-2.6287E-01 1.8583E-01<_>0 -1 2550 -1.2218E-025.8692E-01 -1.9428E-01<_>0 -1 2551 1.2710E-03-1.6689E-01 2.3007E-01<_>0 -1 2552 2.9744E-021.2520E-02 -6.6724E-01<_>0 -1 2553 2.8175E-02-1.7060E-02 6.4579E-01<_>0 -1 2554 3.0345E-02-2.4179E-01 3.4879E-01<_>0 -1 2555 -1.7326E-02-5.3599E-01 2.0996E-01<_>0 -1 2556 -8.4178E-027.5093E-01 -1.7593E-01<_>0 -1 2557 7.4950E-03-1.6188E-01 3.0658E-01<_>0 -1 2558 5.6495E-02-1.7319E-01 1.0016E+00<_>0 -1 2559 -5.2940E-032.3418E-01 -6.5347E-02<_>0 -1 2560 -1.4945E-022.5019E-01 -3.0591E-01<_>0 -1 2561 5.4919E-021.3122E-01 -9.3765E-01<_>0 -1 2562 -1.9722E-02-8.3978E-01 -2.3473E-02<_>0 -1 2563 -6.7159E-022.3587E+00 8.2971E-02<_>0 -1 2564 -1.4326E-021.8814E-01 -3.1222E-01<_>0 -1 2565 2.9841E-021.4825E-01 -8.4682E-01<_>0 -1 2566 5.1883E-02-4.3731E-02 -1.3366E+00<_>0 -1 2567 4.1127E-021.7660E-01 -6.0904E-01<_>0 -1 2568 -1.2865E-01-9.8701E-01 -3.7785E-02<_>0 -1 2569 2.4170E-03-1.6120E-01 3.2676E-01<_>0 -1 2570 7.7030E-03-2.3842E-01 2.9319E-01<_>0 -1 2571 4.5520E-021.4425E-01 -1.5010E+00<_>0 -1 2572 -7.8701E-02-1.0395E+00 -4.5376E-02<_>0 -1 2573 7.8620E-031.9634E-01 -1.4472E-01<_>0 -1 2574 -1.3459E-02-9.0635E-01 -3.8049E-02<_>0 -1 2575 2.8827E-02-2.9474E-02 6.0058E-01<_>0 -1 2576 -2.7366E-02-9.9804E-01 -3.8653E-02<_>0 -1 2577 -7.2918E-027.3361E-01 5.7440E-02<_>0 -1 2578 -1.3989E-022.7893E-01 -2.6516E-01<_>0 -1 2579 4.3243E-024.7760E-03 3.5926E-01<_>0 -1 2580 2.9533E-02-2.0084E-01 5.1203E-01<_>0 -1 2581 -3.1897E-026.4722E-01 -1.3760E-03<_>0 -1 2582 3.7869E-02-1.8364E-01 6.1343E-01<_>0 -1 2583 -2.2418E-02-2.9188E-01 1.8195E-01<_>0 -1 2584 5.8959E-02-6.6452E-02 -1.9290E+00<_>0 -1 2585 3.1223E-02-1.2732E-02 6.1561E-01<_>0 -1 2586 3.7485E-02-2.0857E-01 4.4364E-01<_>0 -1 2587 -2.0966E-02-3.5713E-01 2.4252E-01<_>0 -1 2588 -2.5478E-021.0847E+00 -1.5054E-01<_>0 -1 2589 -7.2570E-032.1303E-01 -1.8308E-01<_>0 -1 2590 -5.0983E-025.1737E-01 -1.8833E-01<_>0 -1 2591 -2.0640E-02-4.4030E-01 2.2746E-01<_>0 -1 2592 1.0673E-023.5060E-02 -5.1665E-01<_>0 -1 2593 3.1896E-021.3228E-02 3.4915E-01<_>0 -1 2594 -2.3825E-023.4119E-01 -2.1510E-01<_>0 -1 2595 -6.0680E-033.2937E-01 -2.8524E-01<_>0 -1 2596 2.3882E-02-2.5334E-01 2.6296E-01<_>0 -1 2597 2.7966E-021.4049E-01 -4.9887E-01<_>0 -1 2598 1.4603E-02-1.5396E-02 -7.6958E-01<_>0 -1 2599 1.0872E-011.9070E-01 -3.2393E-01<_>0 -1 2600 -1.4038E-023.4925E-01 -2.2359E-01<_>0 -1 2601 4.0440E-03-3.8329E-02 5.1177E-01<_>0 -1 2602 -4.9770E-03-4.2888E-01 4.9174E-02<_>0 -1 2603 -8.5183E-026.6625E-01 7.8080E-03<_>0 -1 2604 2.1560E-03-4.9135E-01 6.9556E-02<_>0 -1 2605 3.6384E-011.2997E-01 -1.8950E+00<_>0 -1 2606 2.2083E-01-5.7212E-02 -1.4281E+00<_>0 -1 2607 -1.6140E-02-5.7589E-01 1.8063E-01<_>0 -1 2608 -4.8330E-029.7308E-01 -1.6513E-01<_>0 -1 2609 1.7530E-021.7933E-01 -2.7949E-01<_>0 -1 2610 -3.4310E-02-8.1072E-01 -1.6596E-02<_>0 -1 2611 -4.5830E-032.7909E-01 -7.4520E-03<_>0 -1 2612 1.2896E-01-1.3509E-01 2.5412E+00<_>0 -1 2613 3.0361E-02-6.8419E-02 2.8734E-01<_>0 -1 2614 4.4086E-02-1.8136E-01 6.5413E-01<_>0 -1 2615 3.0160E-03-1.5690E-01 2.6964E-01<_>0 -1 2616 -2.6337E-022.9176E-01 -2.5274E-01<_>0 -1 2617 -2.7866E-024.4388E-01 5.5038E-02<_>0 -1 2618 1.1725E-02-1.9346E-01 4.6657E-01<_>0 -1 2619 1.5690E-03-8.2360E-03 2.5701E-01<_>0 -1 2620 -3.5550E-03-4.2431E-01 7.1174E-02<_>0 -1 2621 -3.1695E-02-8.5394E-01 1.6916E-01<_>0 -1 2622 -3.2097E-028.3785E-01 -1.7597E-01<_>0 -1 2623 1.5544E-019.9550E-02 2.3873E+00<_>0 -1 2624 8.8046E-02-1.8725E-01 6.2384E-01<_>0 -1 2625 -1.6720E-032.5009E-01 -6.5119E-02<_>0 -1 2626 9.3410E-03-3.5379E-01 1.0715E-01<_>0 -1 2627 3.7138E-021.6387E-01 -9.1718E-01<_>0 -1 2628 8.0184E-02-1.4813E-01 1.4895E+00<_>0 -1 2629 -7.9100E-04-2.1327E-01 1.9676E-01<_>0 -1 2630 -5.0400E-03-7.1319E-01 1.8240E-03<_>0 -1 2631 1.1962E-013.3099E-02 1.0442E+00<_>0 -1 2632 -4.5280E-03-2.7308E-01 2.7230E-01<_>0 -1 2633 -2.9639E-023.6226E-01 5.6795E-02<_>0 -1 2634 2.6650E-02-4.8041E-02 -9.6724E-01<_>0 -1 2635 4.4422E-021.3053E-01 -3.5077E-01<_>0 -1 2636 -2.4360E-02-1.0767E+00 -5.1223E-02<_>0 -1 2637 1.9735E-022.6238E-02 2.8071E-01<_>0 -1 2638 5.4930E-03-2.6111E-01 2.1011E-01<_>0 -1 2639 -2.3200E-01-1.7748E+00 1.1483E-01<_>0 -1 2640 -2.5614E-022.9901E-01 -2.2502E-01<_>0 -1 2641 -6.4950E-031.9564E-01 -9.9763E-02<_>0 -1 2642 3.9840E-03-4.3022E-01 8.1261E-02<_>0 -1 2643 -3.5813E-02-5.0987E-01 1.6346E-01<_>0 -1 2644 -1.4169E-027.7978E-01 -1.7476E-01<_>0 -1 2645 -1.2642E-01-6.3048E-01 1.2728E-01<_>0 -1 2646 6.8678E-02-4.6448E-02 -1.1129E+00<_>0 -1 2647 8.5865E-021.1835E-01 -4.8235E+00<_>0 -1 2648 1.5512E-02-1.7468E-02 -6.3693E-01<_>0 -1 2649 8.1091E-028.6133E-02 2.4559E+00<_>0 -1 2650 1.8495E-024.0229E-02 -5.0858E-01<_>0 -1 2651 -8.6321E-02-1.9007E+00 1.1019E-01<_>0 -1 2652 7.2355E-02-6.2112E-02 -1.4165E+00<_>0 -1 2653 -7.8179E-028.8849E-01 4.2370E-02<_>0 -1 2654 9.6682E-02-2.2094E-01 3.3575E-01<_>0 -1 2655 -3.9876E-025.7805E-01 4.5348E-02<_>0 -1 2656 -9.5350E-03-5.4176E-01 3.2400E-03<_>0 -1 2657 4.0600E-04-8.1549E-02 3.5838E-01<_>0 -1 2658 1.2108E-02-2.0280E-01 4.3768E-01<_>0 -1 2659 -2.0874E-024.1470E-01 -4.5568E-02<_>0 -1 2660 5.7888E-02-2.9010E-02 -9.1822E-01<_>0 -1 2661 1.3200E-04-1.1772E-01 2.0000E-01<_>0 -1 2662 -1.7137E-023.3005E-01 -2.3055E-01<_>0 -1 2663 3.0655E-02-2.1545E-02 2.6878E-01<_>0 -1 2664 -7.8700E-04-4.4101E-01 4.9158E-02<_>0 -1 2665 8.8037E-021.1782E-01 -2.8293E+00<_>0 -1 2666 -3.9029E-029.1777E-01 -1.5827E-01<_>0 -1 2667 8.0106E-021.1289E-01 -1.9937E+00<_>0 -1 2668 3.9539E-02-1.4357E-01 1.3085E+00<_>0 -1 2669 2.0684E-022.0048E-01 -4.4187E-02<_>0 -1 2670 -6.7038E-023.2619E-01 -2.0550E-01<_>0 -1 2671 4.6815E-021.5825E-01 -9.5535E-01<_>0 -1 2672 7.8444E-02-7.4651E-02 -2.1161E+00<_>0 -1 2673 6.6380E-021.1642E-01 -1.6114E+00<_>0 -1 2674 3.0054E-02-1.6563E-01 7.0025E-01<_>0 -1 2675 1.7120E-022.2628E-01 -4.0115E-01<_>0 -1 2676 2.0073E-02-1.9390E-01 4.4420E-01<_>0 -1 2677 3.3102E-021.1637E-01 -1.5772E+00<_>0 -1 2678 -1.4882E-02-8.9680E-01 -4.2010E-02<_>0 -1 2679 -1.0281E-023.5603E-01 -1.3124E-02<_>0 -1 2680 -2.8695E-02-4.6040E-01 2.6802E-02<_>0 -1 2681 -4.7190E-032.3789E-01 -6.5519E-02<_>0 -1 2682 3.2202E-01-2.8490E-02 -8.4235E-01<_>0 -1 2683 -1.7045E-02-5.0939E-01 1.6058E-01<_>0 -1 2684 -7.3470E-03-5.4155E-01 4.7320E-03<_>0 -1 2685 -3.0002E-02-8.8786E-01 1.3622E-01<_>0 -1 2686 -1.1293E-028.0615E-01 -1.6160E-01<_>0 -1 2687 4.7750E-031.2968E-02 5.5080E-01<_>0 -1 2688 5.0710E-03-4.5728E-02 -1.0766E+00<_>0 -1 2689 1.9344E-017.1262E-02 1.1695E+00<_>0 -1 2690 5.3750E-03-1.9736E-01 3.8207E-01<_>0 -1 2691 -6.8276E-02-5.4372E+00 1.1152E-01<_>0 -1 2692 -3.4933E-024.4793E-01 -1.8658E-01<_>0 -1 2693 5.1220E-03-1.4872E-02 1.8414E-01<_>0 -1 2694 9.5312E-02-1.5117E-01 9.4991E-01<_>0 -1 2695 -6.2849E-024.6474E-01 3.8405E-02<_>0 -1 2696 -1.7041E-01-1.6500E+00 -6.3237E-02<_>0 -1 2697 1.0584E-02-3.8349E-02 4.1914E-01<_>0 -1 2698 -4.1579E-023.4462E-01 -2.1188E-01<_>0 -1 2699 1.2719E-011.2398E-01 -2.1255E+00<_>0 -1 2700 8.2557E-02-6.2024E-02 -1.4876E+00<_>0 -1 2701 8.5293E-021.7088E-02 3.2077E-01<_>0 -1 2702 5.5544E-02-2.7414E-01 1.8976E-01<_>0 -1 2703 4.5650E-03-1.7920E-01 2.7967E-01<_>0 -1 2704 1.2998E-02-3.2298E-01 2.6942E-01<_>0 -1 2705 5.7892E-021.2644E-01 -6.0713E-01<_>0 -1 2706 -2.2824E-02-4.9682E-01 2.2377E-02<_>0 -1 2707 4.8312E-024.3607E-02 4.8538E-01<_>0 -1 2708 2.5714E-02-4.2951E-02 -9.3024E-01<_>0 -1 2709 6.9270E-03-2.9680E-03 3.4296E-01<_>0 -1 2710 -3.4447E-02-1.5300E+00 -6.1015E-02<_>0 -1 2711 2.9388E-023.7596E-02 6.4172E-01<_>0 -1 2712 -2.4320E-039.9089E-02 -3.9688E-01<_>200-2.9928E+00<_>0 -1 2713 -9.5944E-026.2419E-01 -4.5875E-01<_>0 -1 2714 1.6834E-02-9.3073E-01 2.1564E-01<_>0 -1 2715 2.6050E-02-4.0532E-01 4.2257E-01<_>0 -1 2716 3.6500E-049.5288E-02 -6.3298E-01<_>0 -1 2717 -6.6940E-033.7244E-01 -3.0332E-01<_>0 -1 2718 1.8874E-02-2.3357E-01 4.0331E-01<_>0 -1 2719 -1.6300E-044.2887E-02 -7.7797E-01<_>0 -1 2720 -7.6259E-02-4.9628E-01 1.6335E-01<_>0 -1 2721 5.0149E-023.2747E-02 -8.0048E-01<_>0 -1 2722 -2.9240E-03-5.0003E-01 2.5481E-01<_>0 -1 2723 1.6244E-023.8913E-02 -7.0725E-01<_>0 -1 2724 3.7812E-02-6.6268E-02 7.3869E-01<_>0 -1 2725 -1.2320E-024.8696E-01 -2.4486E-01<_>0 -1 2726 5.8004E-021.3459E-01 -1.3232E-01<_>0 -1 2727 4.8630E-03-4.4173E-01 1.4006E-01<_>0 -1 2728 4.5691E-023.1218E-02 8.9818E-01<_>0 -1 2729 2.1321E-021.2008E-02 -8.6066E-01<_>0 -1 2730 1.5679E-011.4056E-02 8.5333E-01<_>0 -1 2731 -1.0329E-022.9023E-01 -2.9479E-01<_>0 -1 2732 2.4290E-03-4.0440E-01 1.9400E-01<_>0 -1 2733 -2.3339E-023.2945E-01 -2.5713E-01<_>0 -1 2734 -6.8970E-03-5.3353E-01 2.1635E-01<_>0 -1 2735 -3.4403E-02-1.4425E+00 -4.4683E-02<_>0 -1 2736 -2.1235E-02-7.9018E-01 1.9084E-01<_>0 -1 2737 2.0620E-03-2.6931E-01 3.1488E-01<_>0 -1 2738 -4.2190E-03-5.4464E-01 1.6575E-01<_>0 -1 2739 -1.4335E-022.2105E-02 -6.2343E-01<_>0 -1 2740 -8.2120E-03-4.9885E-01 1.9237E-01<_>0 -1 2741 -9.3350E-03-7.9131E-01 -1.4144E-02<_>0 -1 2742 -3.7938E-027.9841E-01 -3.3799E-02<_>0 -1 2743 4.7060E-03-3.3163E-01 2.0726E-01<_>0 -1 2744 -4.4500E-03-2.7256E-01 1.8402E-01<_>0 -1 2745 5.2190E-03-5.3096E-01 5.2608E-02<_>0 -1 2746 -9.5400E-03-5.6485E-01 1.9269E-01<_>0 -1 2747 4.4970E-02-1.7412E-01 9.5383E-01<_>0 -1 2748 1.4209E-02-9.1949E-02 2.4836E-01<_>0 -1 2749 1.6380E-01-5.8497E-02 -1.6404E+00<_>0 -1 2750 2.5580E-032.3448E-01 -9.2734E-02<_>0 -1 2751 -3.8500E-031.7881E-01 -3.5844E-01<_>0 -1 2752 -2.5222E-02-4.2903E-01 2.0245E-01<_>0 -1 2753 -1.9415E-025.8016E-01 -1.8806E-01<_>0 -1 2754 1.4420E-023.2847E-02 8.1981E-01<_>0 -1 2755 5.1583E-026.9176E-02 -4.5866E-01<_>0 -1 2756 -3.7960E-02-1.2553E+00 1.4333E-01<_>0 -1 2757 -2.9561E-025.3152E-01 -2.0596E-01<_>0 -1 2758 -3.9111E-021.1659E+00 5.3897E-02<_>0 -1 2759 -2.9159E-023.9308E-01 -2.2185E-01<_>0 -1 2760 -8.3617E-02-7.3744E-01 1.4268E-01<_>0 -1 2761 4.2004E-01-1.4277E-01 1.7895E+00<_>0 -1 2762 6.0005E-021.1977E-01 -1.8886E+00<_>0 -1 2763 -1.8981E-02-1.4148E+00 -5.6523E-02<_>0 -1 2764 -6.0050E-034.4171E-01 -1.0201E-01<_>0 -1 2765 -5.8214E-02-1.3918E+00 -4.8269E-02<_>0 -1 2766 -1.2271E-025.1318E-01 -9.3697E-02<_>0 -1 2767 4.6586E-02-5.7484E-02 -1.4283E+00<_>0 -1 2768 1.2110E-03-8.0892E-02 3.2333E-01<_>0 -1 2769 -8.8642E-02-8.6449E-01 -3.3147E-02<_>0 -1 2770 -2.3185E-025.2162E-01 -1.6168E-02<_>0 -1 2771 4.3090E-02-1.6154E-01 1.0915E+00<_>0 -1 2772 2.0600E-04-1.7091E-01 3.1237E-01<_>0 -1 2773 8.9160E-03-6.7040E-03 -6.8810E-01<_>0 -1 2774 -1.7753E-026.3293E-01 -4.2360E-03<_>0 -1 2775 6.2300E-03-3.3637E-01 1.2791E-01<_>0 -1 2776 2.2770E-02-3.4704E-02 3.9142E-01<_>0 -1 2777 -2.1535E-026.4765E-01 -2.0098E-01<_>0 -1 2778 6.1759E-025.4297E-02 9.0700E-01<_>0 -1 2779 -7.8070E-026.5523E-01 -1.9754E-01<_>0 -1 2780 1.1315E-021.9385E-01 -5.1707E-01<_>0 -1 2781 -2.5590E-02-9.3097E-01 -3.1547E-02<_>0 -1 2782 -3.8059E-02-6.8327E-01 1.2709E-01<_>0 -1 2783 9.7970E-031.5524E-02 -6.3348E-01<_>0 -1 2784 -1.3842E-021.0061E+00 6.2813E-02<_>0 -1 2785 8.3460E-03-2.3383E-01 3.0983E-01<_>0 -1 2786 -7.1440E-02-7.2505E-01 1.7148E-01<_>0 -1 2787 1.0006E-02-2.2072E-01 3.5266E-01<_>0 -1 2788 1.1005E-011.6662E-01 -7.4319E-01<_>0 -1 2789 3.5311E-02-2.3983E-01 4.1436E-01<_>0 -1 2790 -1.1175E-015.1045E-01 2.2320E-03<_>0 -1 2791 -1.1368E-019.0475E-01 -1.6615E-01<_>0 -1 2792 1.6668E-021.4025E-01 -5.2179E-01<_>0 -1 2793 -8.0340E-03-6.6178E-01 3.7640E-03<_>0 -1 2794 -3.3097E-028.0186E-01 5.9385E-02<_>0 -1 2795 1.2548E-02-3.3546E-01 1.4579E-01<_>0 -1 2796 -4.2074E-02-5.5509E-01 1.3267E-01<_>0 -1 2797 2.5222E-02-6.1632E-02 -1.3679E+00<_>0 -1 2798 -2.4269E-023.4185E-01 -7.4160E-03<_>0 -1 2799 -1.2280E-022.7746E-01 -3.1034E-01<_>0 -1 2800 -1.1377E-011.1720E+00 8.3681E-02<_>0 -1 2801 -8.4772E-028.1695E-01 -1.7838E-01<_>0 -1 2802 -2.4552E-02-1.8627E-01 1.4340E-01<_>0 -1 2803 -9.0270E-033.2659E-01 -2.3541E-01<_>0 -1 2804 1.1178E-021.9761E-01 -2.1701E-02<_>0 -1 2805 -2.9367E-02-9.3415E-01 -2.1705E-02<_>0 -1 2806 6.3640E-032.5573E-02 4.6413E-01<_>0 -1 2807 1.4026E-02-2.1229E-01 4.0079E-01<_>0 -1 2808 -1.3342E-027.4203E-01 2.9002E-02<_>0 -1 2809 2.8423E-01-1.9244E-01 4.3631E-01<_>0 -1 2810 -2.3724E-016.9736E-01 6.9308E-02<_>0 -1 2811 -1.1170E-013.9147E-01 -2.0922E-01<_>0 -1 2812 1.2788E-01-7.2556E-02 3.6088E-01<_>0 -1 2813 -6.2901E-029.5425E-01 -1.5403E-01<_>0 -1 2814 1.7439E-02-5.1135E-02 2.7750E-01<_>0 -1 2815 1.2320E-037.5628E-02 -3.6456E-01<_>0 -1 2816 2.7495E-025.1844E-02 4.1563E-01<_>0 -1 2817 -4.3544E-027.1970E-01 -1.7132E-01<_>0 -1 2818 1.1026E-021.4355E-01 -6.5403E-01<_>0 -1 2819 2.0866E-024.0089E-02 -4.5743E-01<_>0 -1 2820 -2.2304E-025.3855E-01 7.1663E-02<_>0 -1 2821 3.2492E-02-4.5992E-02 -1.0047E+00<_>0 -1 2822 1.2270E-023.4335E-02 4.2432E-01<_>0 -1 2823 8.3820E-03-2.5851E-01 2.6263E-01<_>0 -1 2824 3.7354E-021.5692E-01 -1.0429E+00<_>0 -1 2825 -1.4111E-02-7.3178E-01 -2.0277E-02<_>0 -1 2826 5.7067E-028.3360E-02 1.5661E+00<_>0 -1 2827 4.9680E-03-3.5318E-01 1.4698E-01<_>0 -1 2828 -2.4493E-022.8326E-01 -3.4640E-03<_>0 -1 2829 -1.1255E-02-8.4017E-01 -3.6252E-02<_>0 -1 2830 3.4533E-021.4999E-01 -8.7367E-01<_>0 -1 2831 2.4303E-02-1.8788E-01 5.9484E-01<_>0 -1 2832 -7.8790E-034.4316E-01 -5.6571E-02<_>0 -1 2833 3.5142E-02-5.6495E-02 -1.3617E+00<_>0 -1 2834 4.6260E-03-3.1162E-01 2.5448E-01<_>0 -1 2835 -8.3131E-021.6424E+00 -1.4429E-01<_>0 -1 2836 -1.4016E-02-7.7820E-01 1.7173E-01<_>0 -1 2837 1.2450E-03-2.3191E-01 2.8528E-01<_>0 -1 2838 -1.6803E-02-3.5965E-01 2.0413E-01<_>0 -1 2839 -7.6748E-027.8051E-01 -1.5613E-01<_>0 -1 2840 -2.3672E-011.1814E+00 7.8112E-02<_>0 -1 2841 -1.0057E-01-4.7104E-01 7.9173E-02<_>0 -1 2842 1.3240E-032.2263E-01 -3.7100E-01<_>0 -1 2843 2.2153E-02-3.8649E-02 -9.2275E-01<_>0 -1 2844 -1.1246E-014.1900E-01 8.0411E-02<_>0 -1 2845 1.6481E-02-1.6757E-01 7.1842E-01<_>0 -1 2846 6.8114E-021.5720E-01 -8.7681E-01<_>0 -1 2847 1.6012E-02-4.1600E-03 -5.9328E-01<_>0 -1 2848 4.6640E-03-3.0154E-02 4.8345E-01<_>0 -1 2849 6.7580E-03-2.2667E-01 3.3662E-01<_>0 -1 2850 4.7290E-03-6.0374E-02 3.1458E-01<_>0 -1 2851 2.5870E-03-2.9873E-01 1.7787E-01<_>0 -1 2852 2.8990E-032.1890E-01 -2.9567E-01<_>0 -1 2853 -3.0054E-021.2150E+00 -1.4355E-01<_>0 -1 2854 1.4181E-021.2452E-02 5.5490E-01<_>0 -1 2855 -6.0527E-02-1.4934E+00 -6.5227E-02<_>0 -1 2856 -1.9883E-02-3.8526E-01 1.9761E-01<_>0 -1 2857 3.1219E-02-2.1281E-01 2.9447E-01<_>0 -1 2858 1.8272E-029.7200E-04 6.6814E-01<_>0 -1 2859 1.1090E-03-6.2468E-01 -1.6600E-03<_>0 -1 2860 -3.6714E-02-4.2334E-01 1.2085E-01<_>0 -1 2861 1.2044E-022.5882E-02 -5.0732E-01<_>0 -1 2862 7.4749E-021.3185E-01 -2.1740E-01<_>0 -1 2863 -2.3473E-011.1776E+00 -1.5115E-01<_>0 -1 2864 1.4096E-013.3991E-02 3.9923E-01<_>0 -1 2865 6.1790E-03-3.1807E-01 1.1682E-01<_>0 -1 2866 -5.7217E-028.4399E-01 8.3889E-02<_>0 -1 2867 -5.5227E-023.6888E-01 -1.8913E-01<_>0 -1 2868 -2.1583E-02-5.2162E-01 1.5773E-01<_>0 -1 2869 2.5748E-02-5.9922E-02 -1.0675E+00<_>0 -1 2870 -1.3099E-027.8958E-01 5.2100E-02<_>0 -1 2871 2.2800E-03-1.1704E+00 -5.9357E-02<_>0 -1 2872 8.8060E-034.1718E-02 6.6353E-01<_>0 -1 2873 -8.9700E-03-3.5863E-01 6.0458E-02<_>0 -1 2874 4.0230E-032.0979E-01 -2.4806E-01<_>0 -1 2875 2.5017E-02-1.8796E-01 3.9547E-01<_>0 -1 2876 -5.9010E-032.5664E-01 -9.4919E-02<_>0 -1 2877 4.3850E-033.3139E-02 -4.6075E-01<_>0 -1 2878 -3.3772E-02-9.8882E-01 1.4637E-01<_>0 -1 2879 4.4523E-02-1.3287E-01 1.5797E+00<_>0 -1 2880 -4.0929E-023.3877E-01 7.4971E-02<_>0 -1 2881 3.9352E-02-1.8328E-01 4.6981E-01<_>0 -1 2882 -7.0323E-02-9.8323E-01 1.1808E-01<_>0 -1 2883 3.5743E-02-3.3051E-02 -8.3611E-01<_>0 -1 2884 -4.2962E-021.1671E+00 8.0692E-02<_>0 -1 2885 -2.1008E-026.3870E-01 -1.7626E-01<_>0 -1 2886 -1.5742E-01-2.3302E-01 1.2517E-01<_>0 -1 2887 7.8660E-03-2.2038E-01 2.7197E-01<_>0 -1 2888 2.3622E-021.6127E-01 -4.3329E-01<_>0 -1 2889 7.4692E-02-1.6992E-01 5.8885E-01<_>0 -1 2890 -6.4800E-042.5843E-01 -3.5912E-02<_>0 -1 2891 -1.6291E-02-7.6764E-01 -2.0473E-02<_>0 -1 2892 -3.3134E-02-2.7180E-01 1.4326E-01<_>0 -1 2893 4.8798E-027.6409E-02 -4.1445E-01<_>0 -1 2894 2.2870E-03-3.8629E-02 2.0754E-01<_>0 -1 2895 4.5304E-02-1.7778E-01 6.3461E-01<_>0 -1 2896 1.0706E-011.8972E-01 -5.1236E-01<_>0 -1 2897 -4.0525E-027.0615E-01 -1.7803E-01<_>0 -1 2898 3.1969E-026.8150E-02 6.8733E-01<_>0 -1 2899 -5.7617E-027.5170E-01 -1.5765E-01<_>0 -1 2900 1.3594E-021.9412E-01 -2.4562E-01<_>0 -1 2901 7.1396E-02-4.6881E-02 -8.8198E-01<_>0 -1 2902 -1.4896E-02-4.4532E-01 1.7680E-01<_>0 -1 2903 -1.0026E-026.5123E-01 -1.6710E-01<_>0 -1 2904 3.7590E-03-5.8301E-02 3.4483E-01<_>0 -1 2905 1.6263E-02-1.5582E-01 8.6433E-01<_>0 -1 2906 -4.0176E-02-6.1029E-01 1.1796E-01<_>0 -1 2907 2.7081E-02-4.9602E-02 -8.9990E-01<_>0 -1 2908 5.2420E-021.1297E-01 -1.0834E+00<_>0 -1 2909 -1.9160E-02-7.9880E-01 -3.4079E-02<_>0 -1 2910 -3.7730E-03-1.9124E-01 2.1535E-01<_>0 -1 2911 7.5762E-02-1.3422E-01 1.6807E+00<_>0 -1 2912 -2.2173E-024.8601E-01 3.6160E-03<_><_>6 4 12 9 -1.<_>6 7 12 3 3.<_><_>6 4 12 7 -1.<_>10 4 4 7 3.<_><_>3 9 18 9 -1.<_>3 12 18 3 3.<_><_>8 18 9 6 -1.<_>8 20 9 2 3.<_><_>3 5 4 19 -1.<_>5 5 2 19 2.<_><_>6 5 12 16 -1.<_>6 13 12 8 2.<_><_>5 8 12 6 -1.<_>5 11 12 3 2.<_><_>11 14 4 10 -1.<_>11 19 4 5 2.<_><_>4 0 7 6 -1.<_>4 3 7 3 2.<_><_>6 6 12 6 -1.<_>6 8 12 2 3.<_><_>6 4 12 7 -1.<_>10 4 4 7 3.<_><_>1 8 19 12 -1.<_>1 12 19 4 3.<_><_>0 2 24 3 -1.<_>8 2 8 3 3.<_><_>9 9 6 15 -1.<_>9 14 6 5 3.<_><_>5 6 14 10 -1.<_>5 11 14 5 2.<_><_>5 0 14 9 -1.<_>5 3 14 3 3.<_><_>13 11 9 6 -1.<_>16 11 3 6 3.<_><_>7 5 6 10 -1.<_>9 5 2 10 3.<_><_>10 8 6 10 -1.<_>12 8 2 10 3.<_><_>2 5 4 9 -1.<_>4 5 2 9 2.<_><_>18 0 6 11 -1.<_>20 0 2 11 3.<_><_>0 6 24 13 -1.<_>8 6 8 13 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>7 18 10 6 -1.<_>7 20 10 2 3.<_><_>5 7 14 12 -1.<_>5 13 14 6 2.<_><_>0 3 24 3 -1.<_>8 3 8 3 3.<_><_>5 8 15 6 -1.<_>5 11 15 3 2.<_><_>9 6 5 14 -1.<_>9 13 5 7 2.<_><_>9 5 6 10 -1.<_>11 5 2 10 3.<_><_>6 6 3 12 -1.<_>6 12 3 6 2.<_><_>3 21 18 3 -1.<_>9 21 6 3 3.<_><_>5 6 13 6 -1.<_>5 8 13 2 3.<_><_>18 1 6 15 -1.<_>18 1 3 15 2.<_><_>1 1 6 15 -1.<_>4 1 3 15 2.<_><_>0 8 24 15 -1.<_>8 8 8 15 3.<_><_>5 6 14 12 -1.<_>5 6 7 6 2.<_>12 12 7 6 2.<_><_>2 12 21 12 -1.<_>2 16 21 4 3.<_><_>8 1 4 10 -1.<_>10 1 2 10 2.<_><_>2 13 20 10 -1.<_>2 13 10 10 2.<_><_>0 1 6 13 -1.<_>2 1 2 13 3.<_><_>20 2 4 13 -1.<_>20 2 2 13 2.<_><_>0 5 22 19 -1.<_>11 5 11 19 2.<_><_>18 4 6 9 -1.<_>20 4 2 9 3.<_><_>0 3 6 11 -1.<_>2 3 2 11 3.<_><_>12 1 4 9 -1.<_>12 1 2 9 2.<_><_>0 6 19 3 -1.<_>0 7 19 1 3.<_><_>12 1 4 9 -1.<_>12 1 2 9 2.<_><_>8 1 4 9 -1.<_>10 1 2 9 2.<_><_>5 5 14 14 -1.<_>12 5 7 7 2.<_>5 12 7 7 2.<_><_>1 10 18 2 -1.<_>1 11 18 1 2.<_><_>17 13 4 11 -1.<_>17 13 2 11 2.<_><_>0 4 6 9 -1.<_>0 7 6 3 3.<_><_>6 4 12 9 -1.<_>6 7 12 3 3.<_><_>6 5 12 6 -1.<_>10 5 4 6 3.<_><_>0 1 24 5 -1.<_>8 1 8 5 3.<_><_>4 10 18 6 -1.<_>4 12 18 2 3.<_><_>2 17 12 6 -1.<_>2 17 6 3 2.<_>8 20 6 3 2.<_><_>19 3 4 13 -1.<_>19 3 2 13 2.<_><_>1 3 4 13 -1.<_>3 3 2 13 2.<_><_>0 1 24 23 -1.<_>8 1 8 23 3.<_><_>1 7 8 12 -1.<_>1 11 8 4 3.<_><_>14 7 3 14 -1.<_>14 14 3 7 2.<_><_>3 12 16 6 -1.<_>3 12 8 3 2.<_>11 15 8 3 2.<_><_>6 6 12 6 -1.<_>6 8 12 2 3.<_><_>8 7 6 12 -1.<_>8 13 6 6 2.<_><_>15 15 9 6 -1.<_>15 17 9 2 3.<_><_>1 17 18 3 -1.<_>1 18 18 1 3.<_><_>4 4 16 12 -1.<_>4 10 16 6 2.<_><_>0 1 4 20 -1.<_>2 1 2 20 2.<_><_>3 0 18 2 -1.<_>3 1 18 1 2.<_><_>1 5 20 14 -1.<_>1 5 10 7 2.<_>11 12 10 7 2.<_><_>5 8 14 12 -1.<_>5 12 14 4 3.<_><_>3 14 7 9 -1.<_>3 17 7 3 3.<_><_>14 15 9 6 -1.<_>14 17 9 2 3.<_><_>1 15 9 6 -1.<_>1 17 9 2 3.<_><_>11 6 8 10 -1.<_>15 6 4 5 2.<_>11 11 4 5 2.<_><_>5 5 14 14 -1.<_>5 5 7 7 2.<_>12 12 7 7 2.<_><_>6 0 12 5 -1.<_>10 0 4 5 3.<_><_>9 0 6 9 -1.<_>9 3 6 3 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>10 6 6 9 -1.<_>12 6 2 9 3.<_><_>8 6 6 9 -1.<_>10 6 2 9 3.<_><_>3 8 18 4 -1.<_>9 8 6 4 3.<_><_>6 0 12 9 -1.<_>6 3 12 3 3.<_><_>0 0 24 6 -1.<_>8 0 8 6 3.<_><_>4 7 16 12 -1.<_>4 11 16 4 3.<_><_>11 6 6 6 -1.<_>11 6 3 6 2.<_><_>0 20 24 3 -1.<_>8 20 8 3 3.<_><_>11 6 4 9 -1.<_>11 6 2 9 2.<_><_>4 13 15 4 -1.<_>9 13 5 4 3.<_><_>11 6 4 9 -1.<_>11 6 2 9 2.<_><_>9 6 4 9 -1.<_>11 6 2 9 2.<_><_>9 12 6 12 -1.<_>9 18 6 6 2.<_><_>1 22 18 2 -1.<_>1 23 18 1 2.<_><_>10 7 4 10 -1.<_>10 12 4 5 2.<_><_>6 7 8 10 -1.<_>6 12 8 5 2.<_><_>7 6 10 6 -1.<_>7 8 10 2 3.<_><_>0 14 10 4 -1.<_>0 16 10 2 2.<_><_>6 18 18 2 -1.<_>6 19 18 1 2.<_><_>1 1 22 3 -1.<_>1 2 22 1 3.<_><_>6 16 18 3 -1.<_>6 17 18 1 3.<_><_>2 4 6 15 -1.<_>5 4 3 15 2.<_><_>20 4 4 10 -1.<_>20 4 2 10 2.<_><_>0 4 4 10 -1.<_>2 4 2 10 2.<_><_>2 16 20 6 -1.<_>12 16 10 3 2.<_>2 19 10 3 2.<_><_>0 12 8 9 -1.<_>4 12 4 9 2.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>5 10 6 6 -1.<_>8 10 3 6 2.<_><_>11 8 12 6 -1.<_>17 8 6 3 2.<_>11 11 6 3 2.<_><_>0 8 12 6 -1.<_>0 8 6 3 2.<_>6 11 6 3 2.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>6 0 6 9 -1.<_>8 0 2 9 3.<_><_>8 14 9 6 -1.<_>8 16 9 2 3.<_><_>0 16 9 6 -1.<_>0 18 9 2 3.<_><_>10 8 6 10 -1.<_>12 8 2 10 3.<_><_>3 19 12 3 -1.<_>9 19 6 3 2.<_><_>2 10 20 2 -1.<_>2 11 20 1 2.<_><_>2 9 18 12 -1.<_>2 9 9 6 2.<_>11 15 9 6 2.<_><_>3 0 18 24 -1.<_>3 0 9 24 2.<_><_>5 6 14 10 -1.<_>5 6 7 5 2.<_>12 11 7 5 2.<_><_>9 5 10 12 -1.<_>14 5 5 6 2.<_>9 11 5 6 2.<_><_>4 5 12 12 -1.<_>4 5 6 6 2.<_>10 11 6 6 2.<_><_>4 14 18 3 -1.<_>4 15 18 1 3.<_><_>6 13 8 8 -1.<_>6 17 8 4 2.<_><_>3 16 18 6 -1.<_>3 19 18 3 2.<_><_>0 0 6 6 -1.<_>3 0 3 6 2.<_><_>6 6 12 18 -1.<_>10 6 4 18 3.<_><_>6 1 4 14 -1.<_>8 1 2 14 2.<_><_>3 2 19 2 -1.<_>3 3 19 1 2.<_><_>1 8 22 13 -1.<_>12 8 11 13 2.<_><_>8 9 11 4 -1.<_>8 11 11 2 2.<_><_>0 12 15 10 -1.<_>5 12 5 10 3.<_><_>12 16 12 6 -1.<_>16 16 4 6 3.<_><_>0 16 12 6 -1.<_>4 16 4 6 3.<_><_>19 1 5 12 -1.<_>19 5 5 4 3.<_><_>0 2 24 4 -1.<_>8 2 8 4 3.<_><_>6 8 12 4 -1.<_>6 10 12 2 2.<_><_>7 5 9 6 -1.<_>10 5 3 6 3.<_><_>9 17 6 6 -1.<_>9 20 6 3 2.<_><_>0 7 22 15 -1.<_>0 12 22 5 3.<_><_>4 1 17 9 -1.<_>4 4 17 3 3.<_><_>7 5 6 10 -1.<_>9 5 2 10 3.<_><_>18 1 6 8 -1.<_>18 1 3 8 2.<_><_>0 1 6 7 -1.<_>3 1 3 7 2.<_><_>18 0 6 22 -1.<_>18 0 3 22 2.<_><_>0 0 6 22 -1.<_>3 0 3 22 2.<_><_>16 7 8 16 -1.<_>16 7 4 16 2.<_><_>2 10 19 6 -1.<_>2 12 19 2 3.<_><_>9 9 6 12 -1.<_>9 13 6 4 3.<_><_>2 15 17 6 -1.<_>2 17 17 2 3.<_><_>14 7 3 14 -1.<_>14 14 3 7 2.<_><_>5 6 8 10 -1.<_>5 6 4 5 2.<_>9 11 4 5 2.<_><_>15 8 9 11 -1.<_>18 8 3 11 3.<_><_>0 8 9 11 -1.<_>3 8 3 11 3.<_><_>8 6 10 18 -1.<_>8 15 10 9 2.<_><_>7 7 3 14 -1.<_>7 14 3 7 2.<_><_>0 14 24 8 -1.<_>8 14 8 8 3.<_><_>1 10 18 14 -1.<_>10 10 9 14 2.<_><_>14 12 6 6 -1.<_>14 15 6 3 2.<_><_>7 0 10 16 -1.<_>7 0 5 8 2.<_>12 8 5 8 2.<_><_>10 0 9 6 -1.<_>13 0 3 6 3.<_><_>4 3 16 4 -1.<_>12 3 8 4 2.<_><_>10 0 9 6 -1.<_>13 0 3 6 3.<_><_>1 1 20 4 -1.<_>1 1 10 2 2.<_>11 3 10 2 2.<_><_>10 0 9 6 -1.<_>13 0 3 6 3.<_><_>5 0 9 6 -1.<_>8 0 3 6 3.<_><_>8 18 10 6 -1.<_>8 20 10 2 3.<_><_>6 3 6 9 -1.<_>8 3 2 9 3.<_><_>7 3 12 6 -1.<_>7 5 12 2 3.<_><_>0 10 18 3 -1.<_>0 11 18 1 3.<_><_>1 10 22 3 -1.<_>1 11 22 1 3.<_><_>5 11 8 8 -1.<_>9 11 4 8 2.<_><_>12 11 6 6 -1.<_>12 11 3 6 2.<_><_>6 11 6 6 -1.<_>9 11 3 6 2.<_><_>7 10 11 6 -1.<_>7 12 11 2 3.<_><_>0 13 24 4 -1.<_>0 13 12 2 2.<_>12 15 12 2 2.<_><_>2 4 22 12 -1.<_>13 4 11 6 2.<_>2 10 11 6 2.<_><_>2 0 20 17 -1.<_>12 0 10 17 2.<_><_>14 0 2 24 -1.<_>14 0 1 24 2.<_><_>8 0 2 24 -1.<_>9 0 1 24 2.<_><_>14 1 2 22 -1.<_>14 1 1 22 2.<_><_>8 1 2 22 -1.<_>9 1 1 22 2.<_><_>17 6 3 18 -1.<_>18 6 1 18 3.<_><_>6 14 9 6 -1.<_>6 16 9 2 3.<_><_>13 14 9 4 -1.<_>13 16 9 2 2.<_><_>3 18 18 3 -1.<_>3 19 18 1 3.<_><_>9 4 8 18 -1.<_>13 4 4 9 2.<_>9 13 4 9 2.<_><_>0 17 18 3 -1.<_>0 18 18 1 3.<_><_>0 2 12 4 -1.<_>6 2 6 4 2.<_><_>6 8 14 6 -1.<_>6 11 14 3 2.<_><_>7 5 6 6 -1.<_>10 5 3 6 2.<_><_>10 5 6 16 -1.<_>10 13 6 8 2.<_><_>1 4 9 16 -1.<_>4 4 3 16 3.<_><_>5 0 18 9 -1.<_>5 3 18 3 3.<_><_>9 15 5 8 -1.<_>9 19 5 4 2.<_><_>20 0 4 9 -1.<_>20 0 2 9 2.<_><_>2 0 18 3 -1.<_>2 1 18 1 3.<_><_>5 22 19 2 -1.<_>5 23 19 1 2.<_><_>0 0 4 9 -1.<_>2 0 2 9 2.<_><_>5 6 19 18 -1.<_>5 12 19 6 3.<_><_>0 1 6 9 -1.<_>2 1 2 9 3.<_><_>6 5 14 12 -1.<_>13 5 7 6 2.<_>6 11 7 6 2.<_><_>0 1 20 2 -1.<_>0 2 20 1 2.<_><_>1 2 22 3 -1.<_>1 3 22 1 3.<_><_>2 8 7 9 -1.<_>2 11 7 3 3.<_><_>2 12 22 4 -1.<_>13 12 11 2 2.<_>2 14 11 2 2.<_><_>0 12 22 4 -1.<_>0 12 11 2 2.<_>11 14 11 2 2.<_><_>9 7 6 11 -1.<_>11 7 2 11 3.<_><_>7 1 9 6 -1.<_>10 1 3 6 3.<_><_>11 2 4 10 -1.<_>11 7 4 5 2.<_><_>6 4 12 12 -1.<_>6 10 12 6 2.<_><_>18 1 6 15 -1.<_>18 6 6 5 3.<_><_>3 15 18 3 -1.<_>3 16 18 1 3.<_><_>18 5 6 9 -1.<_>18 8 6 3 3.<_><_>1 5 16 6 -1.<_>1 5 8 3 2.<_>9 8 8 3 2.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>0 4 24 14 -1.<_>0 4 12 7 2.<_>12 11 12 7 2.<_><_>13 0 4 13 -1.<_>13 0 2 13 2.<_><_>7 0 4 13 -1.<_>9 0 2 13 2.<_><_>11 6 6 9 -1.<_>13 6 2 9 3.<_><_>8 7 6 9 -1.<_>10 7 2 9 3.<_><_>13 17 9 6 -1.<_>13 19 9 2 3.<_><_>2 18 14 6 -1.<_>2 18 7 3 2.<_>9 21 7 3 2.<_><_>3 18 18 4 -1.<_>12 18 9 2 2.<_>3 20 9 2 2.<_><_>0 20 15 4 -1.<_>5 20 5 4 3.<_><_>9 15 15 9 -1.<_>14 15 5 9 3.<_><_>4 4 16 4 -1.<_>4 6 16 2 2.<_><_>7 6 10 6 -1.<_>7 8 10 2 3.<_><_>0 14 15 10 -1.<_>5 14 5 10 3.<_><_>7 9 10 14 -1.<_>12 9 5 7 2.<_>7 16 5 7 2.<_><_>7 6 6 9 -1.<_>9 6 2 9 3.<_><_>3 6 18 3 -1.<_>3 7 18 1 3.<_><_>0 10 18 3 -1.<_>0 11 18 1 3.<_><_>3 16 18 4 -1.<_>12 16 9 2 2.<_>3 18 9 2 2.<_><_>4 6 14 6 -1.<_>4 6 7 3 2.<_>11 9 7 3 2.<_><_>13 0 2 18 -1.<_>13 0 1 18 2.<_><_>9 0 2 18 -1.<_>10 0 1 18 2.<_><_>5 7 15 10 -1.<_>10 7 5 10 3.<_><_>1 20 21 4 -1.<_>8 20 7 4 3.<_><_>10 5 5 18 -1.<_>10 14 5 9 2.<_><_>0 2 24 6 -1.<_>0 2 12 3 2.<_>12 5 12 3 2.<_><_>1 1 22 8 -1.<_>12 1 11 4 2.<_>1 5 11 4 2.<_><_>4 0 15 9 -1.<_>4 3 15 3 3.<_><_>0 0 24 19 -1.<_>8 0 8 19 3.<_><_>2 21 18 3 -1.<_>11 21 9 3 2.<_><_>9 7 10 4 -1.<_>9 7 5 4 2.<_><_>5 7 10 4 -1.<_>10 7 5 4 2.<_><_>17 8 6 16 -1.<_>20 8 3 8 2.<_>17 16 3 8 2.<_><_>1 15 20 4 -1.<_>1 15 10 2 2.<_>11 17 10 2 2.<_><_>14 15 10 6 -1.<_>14 17 10 2 3.<_><_>3 0 16 9 -1.<_>3 3 16 3 3.<_><_>15 6 7 15 -1.<_>15 11 7 5 3.<_><_>9 1 6 13 -1.<_>11 1 2 13 3.<_><_>17 2 6 14 -1.<_>17 2 3 14 2.<_><_>3 14 12 10 -1.<_>3 14 6 5 2.<_>9 19 6 5 2.<_><_>7 6 10 6 -1.<_>7 8 10 2 3.<_><_>1 2 6 14 -1.<_>4 2 3 14 2.<_><_>10 4 5 12 -1.<_>10 8 5 4 3.<_><_>0 17 24 5 -1.<_>8 17 8 5 3.<_><_>15 7 5 12 -1.<_>15 11 5 4 3.<_><_>3 1 6 12 -1.<_>3 1 3 6 2.<_>6 7 3 6 2.<_><_>12 13 6 6 -1.<_>12 16 6 3 2.<_><_>6 13 6 6 -1.<_>6 16 6 3 2.<_><_>14 6 3 16 -1.<_>14 14 3 8 2.<_><_>1 12 13 6 -1.<_>1 14 13 2 3.<_><_>13 1 4 9 -1.<_>13 1 2 9 2.<_><_>7 0 9 6 -1.<_>10 0 3 6 3.<_><_>12 2 6 9 -1.<_>12 2 3 9 2.<_><_>6 2 6 9 -1.<_>9 2 3 9 2.<_><_>6 18 12 6 -1.<_>6 20 12 2 3.<_><_>7 6 6 9 -1.<_>9 6 2 9 3.<_><_>7 7 12 3 -1.<_>7 7 6 3 2.<_><_>8 3 8 21 -1.<_>8 10 8 7 3.<_><_>7 4 10 12 -1.<_>7 8 10 4 3.<_><_>0 1 6 9 -1.<_>0 4 6 3 3.<_><_>15 2 2 20 -1.<_>15 2 1 20 2.<_><_>0 3 6 9 -1.<_>0 6 6 3 3.<_><_>15 3 2 21 -1.<_>15 3 1 21 2.<_><_>7 0 2 23 -1.<_>8 0 1 23 2.<_><_>15 8 9 4 -1.<_>15 10 9 2 2.<_><_>0 8 9 4 -1.<_>0 10 9 2 2.<_><_>8 14 9 6 -1.<_>8 16 9 2 3.<_><_>0 14 9 6 -1.<_>0 16 9 2 3.<_><_>3 10 18 4 -1.<_>9 10 6 4 3.<_><_>0 0 24 19 -1.<_>8 0 8 19 3.<_><_>9 1 8 12 -1.<_>9 7 8 6 2.<_><_>10 6 4 10 -1.<_>12 6 2 10 2.<_><_>7 9 10 12 -1.<_>12 9 5 6 2.<_>7 15 5 6 2.<_><_>5 0 3 19 -1.<_>6 0 1 19 3.<_><_>14 0 6 10 -1.<_>16 0 2 10 3.<_><_>2 0 6 12 -1.<_>2 0 3 6 2.<_>5 6 3 6 2.<_><_>0 11 24 2 -1.<_>0 12 24 1 2.<_><_>4 9 13 4 -1.<_>4 11 13 2 2.<_><_>9 8 6 9 -1.<_>9 11 6 3 3.<_><_>0 12 16 4 -1.<_>0 14 16 2 2.<_><_>18 12 6 9 -1.<_>18 15 6 3 3.<_><_>0 12 6 9 -1.<_>0 15 6 3 3.<_><_>8 7 10 4 -1.<_>8 7 5 4 2.<_><_>8 7 6 9 -1.<_>10 7 2 9 3.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>12 3 6 15 -1.<_>14 3 2 15 3.<_><_>6 3 6 15 -1.<_>8 3 2 15 3.<_><_>15 2 9 4 -1.<_>15 4 9 2 2.<_><_>5 10 6 7 -1.<_>8 10 3 7 2.<_><_>9 14 6 10 -1.<_>9 19 6 5 2.<_><_>7 13 5 8 -1.<_>7 17 5 4 2.<_><_>14 5 3 16 -1.<_>14 13 3 8 2.<_><_>2 17 18 3 -1.<_>2 18 18 1 3.<_><_>5 18 19 3 -1.<_>5 19 19 1 3.<_><_>9 0 6 9 -1.<_>11 0 2 9 3.<_><_>12 4 3 18 -1.<_>13 4 1 18 3.<_><_>9 4 3 18 -1.<_>10 4 1 18 3.<_><_>3 3 18 9 -1.<_>9 3 6 9 3.<_><_>6 1 6 14 -1.<_>8 1 2 14 3.<_><_>12 16 9 6 -1.<_>12 19 9 3 2.<_><_>1 3 20 16 -1.<_>1 3 10 8 2.<_>11 11 10 8 2.<_><_>12 5 6 12 -1.<_>15 5 3 6 2.<_>12 11 3 6 2.<_><_>1 2 22 16 -1.<_>1 2 11 8 2.<_>12 10 11 8 2.<_><_>10 14 5 10 -1.<_>10 19 5 5 2.<_><_>3 21 18 3 -1.<_>3 22 18 1 3.<_><_>10 14 6 10 -1.<_>12 14 2 10 3.<_><_>0 2 24 4 -1.<_>8 2 8 4 3.<_><_>6 4 12 9 -1.<_>6 7 12 3 3.<_><_>6 6 12 5 -1.<_>10 6 4 5 3.<_><_>5 8 14 12 -1.<_>5 12 14 4 3.<_><_>4 14 8 10 -1.<_>4 14 4 5 2.<_>8 19 4 5 2.<_><_>11 6 5 14 -1.<_>11 13 5 7 2.<_><_>7 6 3 16 -1.<_>7 14 3 8 2.<_><_>3 7 18 8 -1.<_>9 7 6 8 3.<_><_>2 3 20 2 -1.<_>2 4 20 1 2.<_><_>3 12 19 6 -1.<_>3 14 19 2 3.<_><_>8 6 6 9 -1.<_>10 6 2 9 3.<_><_>16 6 6 14 -1.<_>16 6 3 14 2.<_><_>7 9 6 12 -1.<_>9 9 2 12 3.<_><_>18 6 6 18 -1.<_>21 6 3 9 2.<_>18 15 3 9 2.<_><_>0 6 6 18 -1.<_>0 6 3 9 2.<_>3 15 3 9 2.<_><_>18 2 6 9 -1.<_>18 5 6 3 3.<_><_>3 18 15 6 -1.<_>3 20 15 2 3.<_><_>18 2 6 9 -1.<_>18 5 6 3 3.<_><_>0 2 6 9 -1.<_>0 5 6 3 3.<_><_>5 10 18 2 -1.<_>5 11 18 1 2.<_><_>6 0 12 6 -1.<_>6 2 12 2 3.<_><_>10 0 6 9 -1.<_>12 0 2 9 3.<_><_>8 0 6 9 -1.<_>10 0 2 9 3.<_><_>15 12 9 6 -1.<_>15 14 9 2 3.<_><_>3 6 13 6 -1.<_>3 8 13 2 3.<_><_>15 12 9 6 -1.<_>15 14 9 2 3.<_><_>2 5 6 15 -1.<_>5 5 3 15 2.<_><_>8 8 9 6 -1.<_>11 8 3 6 3.<_><_>8 6 3 14 -1.<_>8 13 3 7 2.<_><_>15 12 9 6 -1.<_>15 14 9 2 3.<_><_>4 12 10 4 -1.<_>9 12 5 4 2.<_><_>13 1 4 19 -1.<_>13 1 2 19 2.<_><_>7 1 4 19 -1.<_>9 1 2 19 2.<_><_>18 9 6 9 -1.<_>18 12 6 3 3.<_><_>1 21 18 3 -1.<_>1 22 18 1 3.<_><_>14 13 10 9 -1.<_>14 16 10 3 3.<_><_>1 13 22 4 -1.<_>1 13 11 2 2.<_>12 15 11 2 2.<_><_>4 6 16 6 -1.<_>12 6 8 3 2.<_>4 9 8 3 2.<_><_>1 0 18 22 -1.<_>1 0 9 11 2.<_>10 11 9 11 2.<_><_>10 7 8 14 -1.<_>14 7 4 7 2.<_>10 14 4 7 2.<_><_>0 4 6 20 -1.<_>0 4 3 10 2.<_>3 14 3 10 2.<_><_>15 0 6 9 -1.<_>17 0 2 9 3.<_><_>3 0 6 9 -1.<_>5 0 2 9 3.<_><_>15 12 6 12 -1.<_>18 12 3 6 2.<_>15 18 3 6 2.<_><_>3 12 6 12 -1.<_>3 12 3 6 2.<_>6 18 3 6 2.<_><_>15 12 9 6 -1.<_>15 14 9 2 3.<_><_>0 12 9 6 -1.<_>0 14 9 2 3.<_><_>4 14 19 3 -1.<_>4 15 19 1 3.<_><_>2 13 19 3 -1.<_>2 14 19 1 3.<_><_>14 15 10 6 -1.<_>14 17 10 2 3.<_><_>6 0 10 12 -1.<_>6 0 5 6 2.<_>11 6 5 6 2.<_><_>17 1 6 12 -1.<_>20 1 3 6 2.<_>17 7 3 6 2.<_><_>1 1 6 12 -1.<_>1 1 3 6 2.<_>4 7 3 6 2.<_><_>16 14 6 9 -1.<_>16 17 6 3 3.<_><_>7 3 9 12 -1.<_>7 9 9 6 2.<_><_>12 1 4 12 -1.<_>12 7 4 6 2.<_><_>4 0 14 8 -1.<_>4 4 14 4 2.<_><_>10 6 6 9 -1.<_>12 6 2 9 3.<_><_>2 10 18 3 -1.<_>8 10 6 3 3.<_><_>15 15 9 6 -1.<_>15 17 9 2 3.<_><_>0 1 21 23 -1.<_>7 1 7 23 3.<_><_>6 9 17 4 -1.<_>6 11 17 2 2.<_><_>1 0 11 18 -1.<_>1 6 11 6 3.<_><_>6 15 13 6 -1.<_>6 17 13 2 3.<_><_>0 15 9 6 -1.<_>0 17 9 2 3.<_><_>8 7 15 4 -1.<_>13 7 5 4 3.<_><_>9 12 6 9 -1.<_>9 15 6 3 3.<_><_>6 8 18 3 -1.<_>12 8 6 3 3.<_><_>0 14 24 4 -1.<_>8 14 8 4 3.<_><_>16 10 3 12 -1.<_>16 16 3 6 2.<_><_>0 3 24 3 -1.<_>0 4 24 1 3.<_><_>14 17 10 6 -1.<_>14 19 10 2 3.<_><_>1 13 18 3 -1.<_>7 13 6 3 3.<_><_>5 0 18 9 -1.<_>5 3 18 3 3.<_><_>4 3 16 9 -1.<_>4 6 16 3 3.<_><_>16 5 3 12 -1.<_>16 11 3 6 2.<_><_>0 7 18 4 -1.<_>6 7 6 4 3.<_><_>10 6 6 9 -1.<_>12 6 2 9 3.<_><_>9 8 6 10 -1.<_>11 8 2 10 3.<_><_>9 15 6 9 -1.<_>11 15 2 9 3.<_><_>3 1 18 21 -1.<_>12 1 9 21 2.<_><_>6 8 12 7 -1.<_>6 8 6 7 2.<_><_>8 5 6 9 -1.<_>10 5 2 9 3.<_><_>0 2 24 4 -1.<_>8 2 8 4 3.<_><_>14 7 5 12 -1.<_>14 11 5 4 3.<_><_>5 7 5 12 -1.<_>5 11 5 4 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>0 1 6 17 -1.<_>3 1 3 17 2.<_><_>3 1 19 9 -1.<_>3 4 19 3 3.<_><_>3 18 12 6 -1.<_>3 18 6 3 2.<_>9 21 6 3 2.<_><_>20 4 4 19 -1.<_>20 4 2 19 2.<_><_>0 16 10 7 -1.<_>5 16 5 7 2.<_><_>8 7 10 12 -1.<_>13 7 5 6 2.<_>8 13 5 6 2.<_><_>6 7 10 12 -1.<_>6 7 5 6 2.<_>11 13 5 6 2.<_><_>9 2 9 6 -1.<_>12 2 3 6 3.<_><_>1 20 21 4 -1.<_>8 20 7 4 3.<_><_>9 12 9 6 -1.<_>9 14 9 2 3.<_><_>7 2 9 6 -1.<_>10 2 3 6 3.<_><_>13 0 4 14 -1.<_>13 0 2 14 2.<_><_>7 0 4 14 -1.<_>9 0 2 14 2.<_><_>14 15 9 6 -1.<_>14 17 9 2 3.<_><_>2 8 18 5 -1.<_>8 8 6 5 3.<_><_>18 3 6 11 -1.<_>20 3 2 11 3.<_><_>6 5 11 14 -1.<_>6 12 11 7 2.<_><_>18 4 6 9 -1.<_>18 7 6 3 3.<_><_>7 6 9 6 -1.<_>7 8 9 2 3.<_><_>18 4 6 9 -1.<_>18 7 6 3 3.<_><_>0 4 6 9 -1.<_>0 7 6 3 3.<_><_>9 4 9 4 -1.<_>9 6 9 2 2.<_><_>0 22 19 2 -1.<_>0 23 19 1 2.<_><_>17 14 6 9 -1.<_>17 17 6 3 3.<_><_>1 14 6 9 -1.<_>1 17 6 3 3.<_><_>14 11 4 9 -1.<_>14 11 2 9 2.<_><_>6 11 4 9 -1.<_>8 11 2 9 2.<_><_>3 9 18 7 -1.<_>9 9 6 7 3.<_><_>9 12 6 10 -1.<_>9 17 6 5 2.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>6 0 6 9 -1.<_>8 0 2 9 3.<_><_>6 17 18 3 -1.<_>6 18 18 1 3.<_><_>1 17 18 3 -1.<_>1 18 18 1 3.<_><_>10 6 11 12 -1.<_>10 12 11 6 2.<_><_>5 6 14 6 -1.<_>5 6 7 3 2.<_>12 9 7 3 2.<_><_>5 4 15 4 -1.<_>5 6 15 2 2.<_><_>0 0 22 2 -1.<_>0 1 22 1 2.<_><_>0 0 24 24 -1.<_>8 0 8 24 3.<_><_>1 15 18 4 -1.<_>10 15 9 4 2.<_><_>6 8 12 9 -1.<_>6 11 12 3 3.<_><_>4 12 7 12 -1.<_>4 16 7 4 3.<_><_>1 2 22 6 -1.<_>12 2 11 3 2.<_>1 5 11 3 2.<_><_>5 20 14 3 -1.<_>12 20 7 3 2.<_><_>0 0 24 16 -1.<_>12 0 12 8 2.<_>0 8 12 8 2.<_><_>3 13 18 4 -1.<_>3 13 9 2 2.<_>12 15 9 2 2.<_><_>2 10 22 2 -1.<_>2 11 22 1 2.<_><_>6 3 11 8 -1.<_>6 7 11 4 2.<_><_>14 5 6 6 -1.<_>14 8 6 3 2.<_><_>0 7 24 6 -1.<_>0 9 24 2 3.<_><_>14 0 10 10 -1.<_>19 0 5 5 2.<_>14 5 5 5 2.<_><_>0 0 10 10 -1.<_>0 0 5 5 2.<_>5 5 5 5 2.<_><_>0 1 24 4 -1.<_>12 1 12 2 2.<_>0 3 12 2 2.<_><_>0 17 18 3 -1.<_>0 18 18 1 3.<_><_>5 15 16 6 -1.<_>13 15 8 3 2.<_>5 18 8 3 2.<_><_>3 15 16 6 -1.<_>3 15 8 3 2.<_>11 18 8 3 2.<_><_>6 16 18 3 -1.<_>6 17 18 1 3.<_><_>0 13 21 10 -1.<_>0 18 21 5 2.<_><_>13 0 6 24 -1.<_>15 0 2 24 3.<_><_>7 4 6 11 -1.<_>9 4 2 11 3.<_><_>9 5 9 6 -1.<_>12 5 3 6 3.<_><_>1 4 2 20 -1.<_>1 14 2 10 2.<_><_>13 0 6 24 -1.<_>15 0 2 24 3.<_><_>5 0 6 24 -1.<_>7 0 2 24 3.<_><_>16 7 6 14 -1.<_>19 7 3 7 2.<_>16 14 3 7 2.<_><_>4 7 4 12 -1.<_>6 7 2 12 2.<_><_>0 5 24 14 -1.<_>8 5 8 14 3.<_><_>5 13 10 6 -1.<_>5 15 10 2 3.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>2 7 6 14 -1.<_>2 7 3 7 2.<_>5 14 3 7 2.<_><_>15 2 9 15 -1.<_>18 2 3 15 3.<_><_>0 2 6 9 -1.<_>2 2 2 9 3.<_><_>12 2 10 14 -1.<_>17 2 5 7 2.<_>12 9 5 7 2.<_><_>11 6 2 18 -1.<_>12 6 1 18 2.<_><_>9 5 15 6 -1.<_>14 5 5 6 3.<_><_>8 6 6 10 -1.<_>10 6 2 10 3.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>3 3 9 7 -1.<_>6 3 3 7 3.<_><_>6 7 14 3 -1.<_>6 7 7 3 2.<_><_>7 7 8 6 -1.<_>11 7 4 6 2.<_><_>12 7 7 12 -1.<_>12 13 7 6 2.<_><_>10 6 4 18 -1.<_>10 6 2 9 2.<_>12 15 2 9 2.<_><_>16 14 6 9 -1.<_>16 17 6 3 3.<_><_>4 0 6 13 -1.<_>6 0 2 13 3.<_><_>2 2 21 3 -1.<_>9 2 7 3 3.<_><_>5 4 5 12 -1.<_>5 8 5 4 3.<_><_>10 3 4 10 -1.<_>10 8 4 5 2.<_><_>8 4 5 8 -1.<_>8 8 5 4 2.<_><_>6 0 11 9 -1.<_>6 3 11 3 3.<_><_>6 6 12 5 -1.<_>10 6 4 5 3.<_><_>0 0 24 5 -1.<_>8 0 8 5 3.<_><_>1 10 23 6 -1.<_>1 12 23 2 3.<_><_>3 21 18 3 -1.<_>9 21 6 3 3.<_><_>3 6 21 6 -1.<_>3 8 21 2 3.<_><_>0 5 6 12 -1.<_>2 5 2 12 3.<_><_>10 2 4 15 -1.<_>10 7 4 5 3.<_><_>8 7 8 10 -1.<_>8 12 8 5 2.<_><_>5 7 15 12 -1.<_>10 7 5 12 3.<_><_>0 17 10 6 -1.<_>0 19 10 2 3.<_><_>14 18 9 6 -1.<_>14 20 9 2 3.<_><_>9 6 6 16 -1.<_>9 14 6 8 2.<_><_>14 18 9 6 -1.<_>14 20 9 2 3.<_><_>1 18 9 6 -1.<_>1 20 9 2 3.<_><_>15 9 9 6 -1.<_>15 11 9 2 3.<_><_>0 9 9 6 -1.<_>0 11 9 2 3.<_><_>17 3 6 9 -1.<_>19 3 2 9 3.<_><_>2 17 18 3 -1.<_>2 18 18 1 3.<_><_>3 15 21 6 -1.<_>3 17 21 2 3.<_><_>9 17 6 6 -1.<_>9 20 6 3 2.<_><_>18 3 6 9 -1.<_>18 6 6 3 3.<_><_>0 3 6 9 -1.<_>0 6 6 3 3.<_><_>4 0 16 10 -1.<_>12 0 8 5 2.<_>4 5 8 5 2.<_><_>2 0 10 16 -1.<_>2 0 5 8 2.<_>7 8 5 8 2.<_><_>14 0 10 5 -1.<_>14 0 5 5 2.<_><_>0 0 10 5 -1.<_>5 0 5 5 2.<_><_>18 3 6 10 -1.<_>18 3 3 10 2.<_><_>5 11 12 6 -1.<_>5 11 6 3 2.<_>11 14 6 3 2.<_><_>21 0 3 18 -1.<_>22 0 1 18 3.<_><_>6 0 6 9 -1.<_>8 0 2 9 3.<_><_>8 8 9 7 -1.<_>11 8 3 7 3.<_><_>7 12 8 10 -1.<_>7 12 4 5 2.<_>11 17 4 5 2.<_><_>21 0 3 18 -1.<_>22 0 1 18 3.<_><_>10 6 4 9 -1.<_>12 6 2 9 2.<_><_>15 0 9 6 -1.<_>15 2 9 2 3.<_><_>0 2 24 3 -1.<_>0 3 24 1 3.<_><_>11 7 6 9 -1.<_>13 7 2 9 3.<_><_>7 6 6 10 -1.<_>9 6 2 10 3.<_><_>12 1 6 12 -1.<_>14 1 2 12 3.<_><_>6 4 12 12 -1.<_>6 10 12 6 2.<_><_>14 3 2 21 -1.<_>14 3 1 21 2.<_><_>6 1 12 8 -1.<_>6 5 12 4 2.<_><_>3 0 18 8 -1.<_>3 4 18 4 2.<_><_>3 0 18 3 -1.<_>3 1 18 1 3.<_><_>0 13 24 4 -1.<_>12 13 12 2 2.<_>0 15 12 2 2.<_><_>10 5 4 9 -1.<_>12 5 2 9 2.<_><_>11 1 6 9 -1.<_>13 1 2 9 3.<_><_>6 2 6 22 -1.<_>8 2 2 22 3.<_><_>16 10 8 14 -1.<_>20 10 4 7 2.<_>16 17 4 7 2.<_><_>3 4 16 15 -1.<_>3 9 16 5 3.<_><_>16 10 8 14 -1.<_>20 10 4 7 2.<_>16 17 4 7 2.<_><_>0 10 8 14 -1.<_>0 10 4 7 2.<_>4 17 4 7 2.<_><_>10 14 11 6 -1.<_>10 17 11 3 2.<_><_>0 7 24 9 -1.<_>8 7 8 9 3.<_><_>13 1 4 16 -1.<_>13 1 2 16 2.<_><_>7 1 4 16 -1.<_>9 1 2 16 2.<_><_>5 5 16 8 -1.<_>13 5 8 4 2.<_>5 9 8 4 2.<_><_>0 9 6 9 -1.<_>0 12 6 3 3.<_><_>6 16 18 3 -1.<_>6 17 18 1 3.<_><_>3 12 6 9 -1.<_>3 15 6 3 3.<_><_>8 14 9 6 -1.<_>8 16 9 2 3.<_><_>2 13 8 10 -1.<_>2 13 4 5 2.<_>6 18 4 5 2.<_><_>15 5 3 18 -1.<_>15 11 3 6 3.<_><_>3 5 18 3 -1.<_>3 6 18 1 3.<_><_>17 5 6 11 -1.<_>19 5 2 11 3.<_><_>1 5 6 11 -1.<_>3 5 2 11 3.<_><_>19 1 4 9 -1.<_>19 1 2 9 2.<_><_>1 1 4 9 -1.<_>3 1 2 9 2.<_><_>4 15 18 9 -1.<_>4 15 9 9 2.<_><_>6 9 12 4 -1.<_>6 11 12 2 2.<_><_>15 2 9 6 -1.<_>15 4 9 2 3.<_><_>0 2 9 6 -1.<_>0 4 9 2 3.<_><_>15 0 6 17 -1.<_>17 0 2 17 3.<_><_>3 0 6 17 -1.<_>5 0 2 17 3.<_><_>8 17 9 4 -1.<_>8 19 9 2 2.<_><_>6 5 3 18 -1.<_>6 11 3 6 3.<_><_>5 2 14 12 -1.<_>5 8 14 6 2.<_><_>10 2 3 12 -1.<_>10 8 3 6 2.<_><_>10 7 14 15 -1.<_>10 12 14 5 3.<_><_>0 7 14 15 -1.<_>0 12 14 5 3.<_><_>15 0 9 6 -1.<_>15 2 9 2 3.<_><_>0 0 9 6 -1.<_>0 2 9 2 3.<_><_>12 6 6 14 -1.<_>14 6 2 14 3.<_><_>9 7 6 9 -1.<_>11 7 2 9 3.<_><_>12 6 6 15 -1.<_>14 6 2 15 3.<_><_>6 6 6 15 -1.<_>8 6 2 15 3.<_><_>15 3 8 9 -1.<_>15 3 4 9 2.<_><_>0 0 9 21 -1.<_>3 0 3 21 3.<_><_>11 9 8 12 -1.<_>11 13 8 4 3.<_><_>6 7 10 12 -1.<_>6 7 5 6 2.<_>11 13 5 6 2.<_><_>10 6 4 18 -1.<_>12 6 2 9 2.<_>10 15 2 9 2.<_><_>0 0 6 9 -1.<_>0 3 6 3 3.<_><_>3 14 18 3 -1.<_>3 15 18 1 3.<_><_>3 14 8 10 -1.<_>3 14 4 5 2.<_>7 19 4 5 2.<_><_>0 12 24 4 -1.<_>12 12 12 2 2.<_>0 14 12 2 2.<_><_>0 2 3 20 -1.<_>1 2 1 20 3.<_><_>12 16 10 8 -1.<_>17 16 5 4 2.<_>12 20 5 4 2.<_><_>2 16 10 8 -1.<_>2 16 5 4 2.<_>7 20 5 4 2.<_><_>7 0 10 9 -1.<_>7 3 10 3 3.<_><_>0 0 24 3 -1.<_>8 0 8 3 3.<_><_>3 8 15 4 -1.<_>3 10 15 2 2.<_><_>6 5 12 6 -1.<_>10 5 4 6 3.<_><_>5 13 14 6 -1.<_>5 16 14 3 2.<_><_>11 14 4 10 -1.<_>11 19 4 5 2.<_><_>0 6 6 7 -1.<_>3 6 3 7 2.<_><_>18 0 6 6 -1.<_>18 0 3 6 2.<_><_>3 1 18 3 -1.<_>3 2 18 1 3.<_><_>9 6 14 18 -1.<_>9 12 14 6 3.<_><_>0 0 6 6 -1.<_>3 0 3 6 2.<_><_>13 11 6 6 -1.<_>13 11 3 6 2.<_><_>0 20 24 3 -1.<_>8 20 8 3 3.<_><_>13 11 6 7 -1.<_>13 11 3 7 2.<_><_>4 12 10 6 -1.<_>4 14 10 2 3.<_><_>13 11 6 6 -1.<_>13 11 3 6 2.<_><_>5 11 6 7 -1.<_>8 11 3 7 2.<_><_>7 4 11 12 -1.<_>7 8 11 4 3.<_><_>6 15 10 4 -1.<_>6 17 10 2 2.<_><_>14 0 6 9 -1.<_>16 0 2 9 3.<_><_>4 0 6 9 -1.<_>6 0 2 9 3.<_><_>11 2 4 15 -1.<_>11 7 4 5 3.<_><_>0 0 20 3 -1.<_>0 1 20 1 3.<_><_>13 18 10 6 -1.<_>13 20 10 2 3.<_><_>2 7 6 11 -1.<_>5 7 3 11 2.<_><_>10 14 10 9 -1.<_>10 17 10 3 3.<_><_>8 2 4 9 -1.<_>10 2 2 9 2.<_><_>14 3 10 4 -1.<_>14 3 5 4 2.<_><_>6 6 12 6 -1.<_>6 6 6 3 2.<_>12 9 6 3 2.<_><_>8 8 8 10 -1.<_>12 8 4 5 2.<_>8 13 4 5 2.<_><_>7 4 4 16 -1.<_>7 12 4 8 2.<_><_>8 8 9 4 -1.<_>8 10 9 2 2.<_><_>5 2 14 9 -1.<_>5 5 14 3 3.<_><_>3 16 19 8 -1.<_>3 20 19 4 2.<_><_>0 0 10 8 -1.<_>5 0 5 8 2.<_><_>5 2 16 18 -1.<_>5 2 8 18 2.<_><_>0 11 24 11 -1.<_>8 11 8 11 3.<_><_>3 3 18 5 -1.<_>3 3 9 5 2.<_><_>1 16 18 3 -1.<_>1 17 18 1 3.<_><_>5 17 18 3 -1.<_>5 18 18 1 3.<_><_>1 13 9 6 -1.<_>1 15 9 2 3.<_><_>1 9 23 10 -1.<_>1 14 23 5 2.<_><_>3 7 18 3 -1.<_>3 8 18 1 3.<_><_>6 8 12 3 -1.<_>6 8 6 3 2.<_><_>6 2 3 22 -1.<_>7 2 1 22 3.<_><_>14 17 10 6 -1.<_>14 19 10 2 3.<_><_>1 18 10 6 -1.<_>1 20 10 2 3.<_><_>11 3 6 12 -1.<_>13 3 2 12 3.<_><_>10 6 4 9 -1.<_>12 6 2 9 2.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>12 10 9 6 -1.<_>15 10 3 6 3.<_><_>2 11 6 9 -1.<_>5 11 3 9 2.<_><_>14 5 3 19 -1.<_>15 5 1 19 3.<_><_>6 6 9 6 -1.<_>6 8 9 2 3.<_><_>14 5 3 19 -1.<_>15 5 1 19 3.<_><_>0 3 6 9 -1.<_>0 6 6 3 3.<_><_>5 21 18 3 -1.<_>5 22 18 1 3.<_><_>1 10 18 4 -1.<_>7 10 6 4 3.<_><_>13 4 8 10 -1.<_>17 4 4 5 2.<_>13 9 4 5 2.<_><_>7 8 9 6 -1.<_>10 8 3 6 3.<_><_>12 9 9 8 -1.<_>15 9 3 8 3.<_><_>0 6 5 12 -1.<_>0 10 5 4 3.<_><_>7 6 14 6 -1.<_>14 6 7 3 2.<_>7 9 7 3 2.<_><_>7 5 3 19 -1.<_>8 5 1 19 3.<_><_>8 4 15 20 -1.<_>13 4 5 20 3.<_><_>1 4 15 20 -1.<_>6 4 5 20 3.<_><_>13 10 6 6 -1.<_>13 10 3 6 2.<_><_>5 10 6 6 -1.<_>8 10 3 6 2.<_><_>14 2 6 14 -1.<_>17 2 3 7 2.<_>14 9 3 7 2.<_><_>4 2 6 14 -1.<_>4 2 3 7 2.<_>7 9 3 7 2.<_><_>12 4 6 7 -1.<_>12 4 3 7 2.<_><_>9 4 6 9 -1.<_>11 4 2 9 3.<_><_>11 4 8 10 -1.<_>11 4 4 10 2.<_><_>5 4 8 10 -1.<_>9 4 4 10 2.<_><_>8 18 10 6 -1.<_>8 20 10 2 3.<_><_>1 18 21 6 -1.<_>1 20 21 2 3.<_><_>9 2 12 6 -1.<_>9 2 6 6 2.<_><_>3 2 12 6 -1.<_>9 2 6 6 2.<_><_>12 5 12 6 -1.<_>18 5 6 3 2.<_>12 8 6 3 2.<_><_>8 8 6 9 -1.<_>8 11 6 3 3.<_><_>2 7 20 6 -1.<_>2 9 20 2 3.<_><_>0 5 12 6 -1.<_>0 5 6 3 2.<_>6 8 6 3 2.<_><_>14 14 8 10 -1.<_>18 14 4 5 2.<_>14 19 4 5 2.<_><_>2 14 8 10 -1.<_>2 14 4 5 2.<_>6 19 4 5 2.<_><_>2 11 20 13 -1.<_>2 11 10 13 2.<_><_>6 9 12 5 -1.<_>12 9 6 5 2.<_><_>5 6 16 6 -1.<_>13 6 8 3 2.<_>5 9 8 3 2.<_><_>1 19 9 4 -1.<_>1 21 9 2 2.<_><_>7 5 12 5 -1.<_>11 5 4 5 3.<_><_>3 5 14 12 -1.<_>3 5 7 6 2.<_>10 11 7 6 2.<_><_>9 4 9 6 -1.<_>12 4 3 6 3.<_><_>2 6 19 3 -1.<_>2 7 19 1 3.<_><_>18 10 6 9 -1.<_>18 13 6 3 3.<_><_>3 7 18 2 -1.<_>3 8 18 1 2.<_><_>20 2 4 18 -1.<_>22 2 2 9 2.<_>20 11 2 9 2.<_><_>2 18 20 3 -1.<_>2 19 20 1 3.<_><_>1 9 22 3 -1.<_>1 10 22 1 3.<_><_>0 2 4 18 -1.<_>0 2 2 9 2.<_>2 11 2 9 2.<_><_>19 0 4 23 -1.<_>19 0 2 23 2.<_><_>0 3 6 19 -1.<_>3 3 3 19 2.<_><_>18 2 6 9 -1.<_>20 2 2 9 3.<_><_>0 5 10 6 -1.<_>0 7 10 2 3.<_><_>7 0 12 12 -1.<_>13 0 6 6 2.<_>7 6 6 6 2.<_><_>0 3 24 6 -1.<_>0 3 12 3 2.<_>12 6 12 3 2.<_><_>10 14 4 10 -1.<_>10 19 4 5 2.<_><_>8 9 4 15 -1.<_>8 14 4 5 3.<_><_>4 11 17 6 -1.<_>4 14 17 3 2.<_><_>2 5 18 8 -1.<_>2 5 9 4 2.<_>11 9 9 4 2.<_><_>7 6 14 6 -1.<_>14 6 7 3 2.<_>7 9 7 3 2.<_><_>3 6 14 6 -1.<_>3 6 7 3 2.<_>10 9 7 3 2.<_><_>16 5 3 18 -1.<_>17 5 1 18 3.<_><_>5 5 3 18 -1.<_>6 5 1 18 3.<_><_>10 10 14 4 -1.<_>10 12 14 2 2.<_><_>4 10 9 4 -1.<_>4 12 9 2 2.<_><_>2 0 18 9 -1.<_>2 3 18 3 3.<_><_>6 3 12 8 -1.<_>10 3 4 8 3.<_><_>1 1 8 5 -1.<_>5 1 4 5 2.<_><_>12 7 7 8 -1.<_>12 11 7 4 2.<_><_>0 12 22 4 -1.<_>0 14 22 2 2.<_><_>15 6 4 15 -1.<_>15 11 4 5 3.<_><_>5 7 7 8 -1.<_>5 11 7 4 2.<_><_>8 18 9 4 -1.<_>8 20 9 2 2.<_><_>1 2 22 4 -1.<_>1 4 22 2 2.<_><_>17 3 6 17 -1.<_>19 3 2 17 3.<_><_>8 2 8 18 -1.<_>8 11 8 9 2.<_><_>17 0 6 12 -1.<_>20 0 3 6 2.<_>17 6 3 6 2.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>15 5 9 12 -1.<_>15 11 9 6 2.<_><_>2 22 18 2 -1.<_>2 23 18 1 2.<_><_>10 10 12 6 -1.<_>16 10 6 3 2.<_>10 13 6 3 2.<_><_>0 1 4 11 -1.<_>2 1 2 11 2.<_><_>20 0 4 10 -1.<_>20 0 2 10 2.<_><_>1 3 6 17 -1.<_>3 3 2 17 3.<_><_>15 15 9 6 -1.<_>15 17 9 2 3.<_><_>0 13 8 9 -1.<_>0 16 8 3 3.<_><_>16 8 6 12 -1.<_>16 12 6 4 3.<_><_>2 8 6 12 -1.<_>2 12 6 4 3.<_><_>10 2 4 15 -1.<_>10 7 4 5 3.<_><_>1 5 19 3 -1.<_>1 6 19 1 3.<_><_>11 8 9 7 -1.<_>14 8 3 7 3.<_><_>3 8 12 9 -1.<_>3 11 12 3 3.<_><_>3 6 18 3 -1.<_>3 7 18 1 3.<_><_>10 0 4 12 -1.<_>10 6 4 6 2.<_><_>3 9 18 14 -1.<_>3 9 9 14 2.<_><_>0 0 4 9 -1.<_>2 0 2 9 2.<_><_>12 5 4 18 -1.<_>12 5 2 18 2.<_><_>8 5 4 18 -1.<_>10 5 2 18 2.<_><_>10 5 6 10 -1.<_>12 5 2 10 3.<_><_>9 4 4 11 -1.<_>11 4 2 11 2.<_><_>4 16 18 3 -1.<_>4 17 18 1 3.<_><_>0 16 20 3 -1.<_>0 17 20 1 3.<_><_>9 9 6 12 -1.<_>9 13 6 4 3.<_><_>8 13 8 8 -1.<_>8 17 8 4 2.<_><_>13 10 3 12 -1.<_>13 16 3 6 2.<_><_>5 9 14 14 -1.<_>5 9 7 7 2.<_>12 16 7 7 2.<_><_>0 0 24 10 -1.<_>12 0 12 5 2.<_>0 5 12 5 2.<_><_>1 11 18 2 -1.<_>1 12 18 1 2.<_><_>19 5 5 12 -1.<_>19 9 5 4 3.<_><_>0 5 5 12 -1.<_>0 9 5 4 3.<_><_>16 6 8 18 -1.<_>20 6 4 9 2.<_>16 15 4 9 2.<_><_>0 6 8 18 -1.<_>0 6 4 9 2.<_>4 15 4 9 2.<_><_>12 5 12 12 -1.<_>18 5 6 6 2.<_>12 11 6 6 2.<_><_>7 6 6 9 -1.<_>9 6 2 9 3.<_><_>9 13 6 11 -1.<_>11 13 2 11 3.<_><_>0 5 12 12 -1.<_>0 5 6 6 2.<_>6 11 6 6 2.<_><_>1 2 23 3 -1.<_>1 3 23 1 3.<_><_>1 15 19 3 -1.<_>1 16 19 1 3.<_><_>13 17 11 4 -1.<_>13 19 11 2 2.<_><_>0 13 8 5 -1.<_>4 13 4 5 2.<_><_>12 10 10 4 -1.<_>12 10 5 4 2.<_><_>4 6 9 9 -1.<_>4 9 9 3 3.<_><_>15 14 9 6 -1.<_>15 16 9 2 3.<_><_>1 12 9 6 -1.<_>1 14 9 2 3.<_><_>3 10 20 8 -1.<_>13 10 10 4 2.<_>3 14 10 4 2.<_><_>2 0 9 18 -1.<_>5 0 3 18 3.<_><_>13 11 9 10 -1.<_>16 11 3 10 3.<_><_>1 2 8 5 -1.<_>5 2 4 5 2.<_><_>3 4 21 6 -1.<_>10 4 7 6 3.<_><_>7 0 10 14 -1.<_>7 0 5 7 2.<_>12 7 5 7 2.<_><_>12 17 12 4 -1.<_>12 19 12 2 2.<_><_>0 6 23 4 -1.<_>0 8 23 2 2.<_><_>13 10 8 10 -1.<_>17 10 4 5 2.<_>13 15 4 5 2.<_><_>0 16 18 3 -1.<_>0 17 18 1 3.<_><_>15 16 9 4 -1.<_>15 18 9 2 2.<_><_>0 16 9 4 -1.<_>0 18 9 2 2.<_><_>13 11 6 6 -1.<_>13 11 3 6 2.<_><_>5 11 6 6 -1.<_>8 11 3 6 2.<_><_>0 3 24 6 -1.<_>12 3 12 3 2.<_>0 6 12 3 2.<_><_>2 4 18 3 -1.<_>2 5 18 1 3.<_><_>0 0 24 4 -1.<_>12 0 12 2 2.<_>0 2 12 2 2.<_><_>1 16 18 3 -1.<_>1 17 18 1 3.<_><_>15 15 9 6 -1.<_>15 17 9 2 3.<_><_>0 15 9 6 -1.<_>0 17 9 2 3.<_><_>6 17 18 3 -1.<_>6 18 18 1 3.<_><_>8 8 6 10 -1.<_>10 8 2 10 3.<_><_>10 6 6 9 -1.<_>12 6 2 9 3.<_><_>8 8 5 8 -1.<_>8 12 5 4 2.<_><_>12 8 6 8 -1.<_>12 12 6 4 2.<_><_>6 5 6 11 -1.<_>8 5 2 11 3.<_><_>13 6 8 9 -1.<_>13 9 8 3 3.<_><_>1 7 21 6 -1.<_>1 9 21 2 3.<_><_>15 5 3 12 -1.<_>15 11 3 6 2.<_><_>6 9 11 12 -1.<_>6 13 11 4 3.<_><_>13 8 10 8 -1.<_>18 8 5 4 2.<_>13 12 5 4 2.<_><_>5 8 12 3 -1.<_>11 8 6 3 2.<_><_>6 11 18 4 -1.<_>12 11 6 4 3.<_><_>0 0 22 22 -1.<_>0 11 22 11 2.<_><_>11 2 6 8 -1.<_>11 6 6 4 2.<_><_>9 0 6 9 -1.<_>11 0 2 9 3.<_><_>10 0 6 9 -1.<_>12 0 2 9 3.<_><_>8 3 6 14 -1.<_>8 3 3 7 2.<_>11 10 3 7 2.<_><_>3 10 18 8 -1.<_>9 10 6 8 3.<_><_>10 0 3 14 -1.<_>10 7 3 7 2.<_><_>4 3 16 20 -1.<_>4 13 16 10 2.<_><_>9 4 6 10 -1.<_>11 4 2 10 3.<_><_>5 0 16 4 -1.<_>5 2 16 2 2.<_><_>2 5 18 4 -1.<_>8 5 6 4 3.<_><_>13 0 6 9 -1.<_>15 0 2 9 3.<_><_>8 4 8 5 -1.<_>12 4 4 5 2.<_><_>12 10 10 4 -1.<_>12 10 5 4 2.<_><_>2 10 10 4 -1.<_>7 10 5 4 2.<_><_>7 11 12 5 -1.<_>11 11 4 5 3.<_><_>3 10 8 10 -1.<_>3 10 4 5 2.<_>7 15 4 5 2.<_><_>11 12 9 8 -1.<_>14 12 3 8 3.<_><_>0 21 24 3 -1.<_>8 21 8 3 3.<_><_>3 20 18 4 -1.<_>9 20 6 4 3.<_><_>1 15 9 6 -1.<_>1 17 9 2 3.<_><_>11 17 10 4 -1.<_>11 19 10 2 2.<_><_>9 12 4 12 -1.<_>9 18 4 6 2.<_><_>9 6 9 6 -1.<_>12 6 3 6 3.<_><_>1 13 6 9 -1.<_>1 16 6 3 3.<_><_>6 16 12 4 -1.<_>6 18 12 2 2.<_><_>1 5 20 3 -1.<_>1 6 20 1 3.<_><_>8 1 9 9 -1.<_>8 4 9 3 3.<_><_>2 19 9 4 -1.<_>2 21 9 2 2.<_><_>11 1 4 18 -1.<_>11 7 4 6 3.<_><_>7 2 8 12 -1.<_>7 2 4 6 2.<_>11 8 4 6 2.<_><_>11 10 9 8 -1.<_>14 10 3 8 3.<_><_>5 11 12 5 -1.<_>9 11 4 5 3.<_><_>11 9 9 6 -1.<_>14 9 3 6 3.<_><_>5 10 6 9 -1.<_>7 10 2 9 3.<_><_>4 7 5 12 -1.<_>4 11 5 4 3.<_><_>2 0 21 6 -1.<_>9 0 7 6 3.<_><_>7 6 10 6 -1.<_>7 8 10 2 3.<_><_>9 0 6 15 -1.<_>11 0 2 15 3.<_><_>2 2 18 2 -1.<_>2 3 18 1 2.<_><_>8 17 8 6 -1.<_>8 20 8 3 2.<_><_>3 0 18 2 -1.<_>3 1 18 1 2.<_><_>8 0 9 6 -1.<_>11 0 3 6 3.<_><_>0 17 18 3 -1.<_>0 18 18 1 3.<_><_>6 7 12 5 -1.<_>10 7 4 5 3.<_><_>0 3 6 9 -1.<_>2 3 2 9 3.<_><_>20 2 4 9 -1.<_>20 2 2 9 2.<_><_>0 2 4 9 -1.<_>2 2 2 9 2.<_><_>0 1 24 4 -1.<_>12 1 12 2 2.<_>0 3 12 2 2.<_><_>0 16 9 6 -1.<_>0 18 9 2 3.<_><_>14 13 9 6 -1.<_>14 15 9 2 3.<_><_>0 15 19 3 -1.<_>0 16 19 1 3.<_><_>1 5 22 12 -1.<_>12 5 11 6 2.<_>1 11 11 6 2.<_><_>5 13 6 6 -1.<_>8 13 3 6 2.<_><_>4 2 20 3 -1.<_>4 3 20 1 3.<_><_>8 14 6 10 -1.<_>10 14 2 10 3.<_><_>6 12 16 6 -1.<_>14 12 8 3 2.<_>6 15 8 3 2.<_><_>2 13 8 9 -1.<_>2 16 8 3 3.<_><_>11 8 6 14 -1.<_>14 8 3 7 2.<_>11 15 3 7 2.<_><_>2 12 16 6 -1.<_>2 12 8 3 2.<_>10 15 8 3 2.<_><_>5 16 16 8 -1.<_>5 20 16 4 2.<_><_>9 1 4 12 -1.<_>9 7 4 6 2.<_><_>8 2 8 10 -1.<_>12 2 4 5 2.<_>8 7 4 5 2.<_><_>6 6 12 6 -1.<_>6 6 6 3 2.<_>12 9 6 3 2.<_><_>10 7 6 9 -1.<_>12 7 2 9 3.<_><_>0 0 8 12 -1.<_>0 0 4 6 2.<_>4 6 4 6 2.<_><_>18 8 6 9 -1.<_>18 11 6 3 3.<_><_>2 12 6 6 -1.<_>5 12 3 6 2.<_><_>3 21 21 3 -1.<_>10 21 7 3 3.<_><_>2 0 16 6 -1.<_>2 3 16 3 2.<_><_>13 6 7 6 -1.<_>13 9 7 3 2.<_><_>6 4 4 14 -1.<_>6 11 4 7 2.<_><_>9 7 6 9 -1.<_>11 7 2 9 3.<_><_>7 8 6 14 -1.<_>7 8 3 7 2.<_>10 15 3 7 2.<_><_>18 8 4 16 -1.<_>18 16 4 8 2.<_><_>9 14 6 10 -1.<_>11 14 2 10 3.<_><_>6 11 12 5 -1.<_>10 11 4 5 3.<_><_>0 12 23 3 -1.<_>0 13 23 1 3.<_><_>13 0 6 12 -1.<_>15 0 2 12 3.<_><_>0 10 12 5 -1.<_>4 10 4 5 3.<_><_>13 2 10 4 -1.<_>13 4 10 2 2.<_><_>5 0 6 12 -1.<_>7 0 2 12 3.<_><_>11 6 9 6 -1.<_>14 6 3 6 3.<_><_>4 6 9 6 -1.<_>7 6 3 6 3.<_><_>6 11 18 13 -1.<_>12 11 6 13 3.<_><_>0 11 18 13 -1.<_>6 11 6 13 3.<_><_>12 16 12 6 -1.<_>16 16 4 6 3.<_><_>0 6 21 3 -1.<_>0 7 21 1 3.<_><_>12 16 12 6 -1.<_>16 16 4 6 3.<_><_>5 7 6 14 -1.<_>5 14 6 7 2.<_><_>5 10 19 2 -1.<_>5 11 19 1 2.<_><_>5 4 14 4 -1.<_>5 6 14 2 2.<_><_>3 18 18 4 -1.<_>9 18 6 4 3.<_><_>7 0 4 9 -1.<_>9 0 2 9 2.<_><_>13 3 11 4 -1.<_>13 5 11 2 2.<_><_>2 0 9 6 -1.<_>5 0 3 6 3.<_><_>19 1 4 23 -1.<_>19 1 2 23 2.<_><_>1 1 4 23 -1.<_>3 1 2 23 2.<_><_>5 16 18 3 -1.<_>5 17 18 1 3.<_><_>0 3 11 4 -1.<_>0 5 11 2 2.<_><_>2 16 20 3 -1.<_>2 17 20 1 3.<_><_>5 3 13 4 -1.<_>5 5 13 2 2.<_><_>1 9 22 15 -1.<_>1 9 11 15 2.<_><_>3 4 14 3 -1.<_>10 4 7 3 2.<_><_>8 7 10 4 -1.<_>8 7 5 4 2.<_><_>6 7 10 4 -1.<_>11 7 5 4 2.<_><_>10 4 6 9 -1.<_>12 4 2 9 3.<_><_>1 12 9 6 -1.<_>4 12 3 6 3.<_><_>8 3 8 10 -1.<_>12 3 4 5 2.<_>8 8 4 5 2.<_><_>3 6 16 6 -1.<_>3 6 8 3 2.<_>11 9 8 3 2.<_><_>5 6 14 6 -1.<_>5 9 14 3 2.<_><_>4 3 9 6 -1.<_>4 5 9 2 3.<_><_>6 3 18 2 -1.<_>6 4 18 1 2.<_><_>7 6 9 6 -1.<_>10 6 3 6 3.<_><_>0 1 24 3 -1.<_>0 2 24 1 3.<_><_>0 17 10 6 -1.<_>0 19 10 2 3.<_><_>3 18 18 3 -1.<_>3 19 18 1 3.<_><_>2 5 6 16 -1.<_>2 5 3 8 2.<_>5 13 3 8 2.<_><_>7 6 11 6 -1.<_>7 8 11 2 3.<_><_>5 2 12 22 -1.<_>5 13 12 11 2.<_><_>10 7 4 10 -1.<_>10 12 4 5 2.<_><_>9 0 4 18 -1.<_>9 6 4 6 3.<_><_>18 8 6 9 -1.<_>18 11 6 3 3.<_><_>4 7 15 10 -1.<_>9 7 5 10 3.<_><_>10 5 6 9 -1.<_>12 5 2 9 3.<_><_>9 9 6 10 -1.<_>11 9 2 10 3.<_><_>11 14 6 10 -1.<_>13 14 2 10 3.<_><_>7 14 6 10 -1.<_>9 14 2 10 3.<_><_>4 8 16 9 -1.<_>4 11 16 3 3.<_><_>2 11 20 3 -1.<_>2 12 20 1 3.<_><_>13 0 4 13 -1.<_>13 0 2 13 2.<_><_>7 0 4 13 -1.<_>9 0 2 13 2.<_><_>3 1 18 7 -1.<_>9 1 6 7 3.<_><_>1 11 6 9 -1.<_>1 14 6 3 3.<_><_>8 18 9 6 -1.<_>8 20 9 2 3.<_><_>3 9 15 6 -1.<_>3 11 15 2 3.<_><_>5 10 19 2 -1.<_>5 11 19 1 2.<_><_>8 6 7 16 -1.<_>8 14 7 8 2.<_><_>9 14 9 6 -1.<_>9 16 9 2 3.<_><_>0 7 8 12 -1.<_>0 11 8 4 3.<_><_>6 4 18 3 -1.<_>6 5 18 1 3.<_><_>0 16 12 6 -1.<_>4 16 4 6 3.<_><_>13 13 9 4 -1.<_>13 15 9 2 2.<_><_>5 8 14 14 -1.<_>5 8 7 7 2.<_>12 15 7 7 2.<_><_>1 16 22 6 -1.<_>12 16 11 3 2.<_>1 19 11 3 2.<_><_>9 0 6 9 -1.<_>11 0 2 9 3.<_><_>9 5 10 10 -1.<_>14 5 5 5 2.<_>9 10 5 5 2.<_><_>5 5 10 10 -1.<_>5 5 5 5 2.<_>10 10 5 5 2.<_><_>4 6 16 6 -1.<_>12 6 8 3 2.<_>4 9 8 3 2.<_><_>0 7 6 9 -1.<_>0 10 6 3 3.<_><_>16 10 8 14 -1.<_>20 10 4 7 2.<_>16 17 4 7 2.<_><_>9 12 6 12 -1.<_>9 18 6 6 2.<_><_>8 10 8 12 -1.<_>12 10 4 6 2.<_>8 16 4 6 2.<_><_>8 0 4 9 -1.<_>10 0 2 9 2.<_><_>10 4 8 16 -1.<_>14 4 4 8 2.<_>10 12 4 8 2.<_><_>7 10 10 6 -1.<_>7 12 10 2 3.<_><_>5 6 14 14 -1.<_>12 6 7 7 2.<_>5 13 7 7 2.<_><_>2 11 20 2 -1.<_>2 12 20 1 2.<_><_>18 8 4 16 -1.<_>18 16 4 8 2.<_><_>1 11 12 10 -1.<_>1 11 6 5 2.<_>7 16 6 5 2.<_><_>6 9 12 4 -1.<_>6 11 12 2 2.<_><_>9 12 6 7 -1.<_>12 12 3 7 2.<_><_>10 4 8 16 -1.<_>14 4 4 8 2.<_>10 12 4 8 2.<_><_>6 4 8 16 -1.<_>6 4 4 8 2.<_>10 12 4 8 2.<_><_>8 9 9 6 -1.<_>11 9 3 6 3.<_><_>1 5 16 12 -1.<_>1 5 8 6 2.<_>9 11 8 6 2.<_><_>9 9 6 8 -1.<_>9 9 3 8 2.<_><_>6 0 3 18 -1.<_>7 0 1 18 3.<_><_>17 9 5 14 -1.<_>17 16 5 7 2.<_><_>2 9 5 14 -1.<_>2 16 5 7 2.<_><_>7 4 10 6 -1.<_>7 7 10 3 2.<_><_>1 3 23 18 -1.<_>1 9 23 6 3.<_><_>1 1 21 3 -1.<_>8 1 7 3 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>3 18 12 6 -1.<_>3 18 6 3 2.<_>9 21 6 3 2.<_><_>16 8 8 16 -1.<_>20 8 4 8 2.<_>16 16 4 8 2.<_><_>0 19 24 4 -1.<_>8 19 8 4 3.<_><_>16 8 8 16 -1.<_>20 8 4 8 2.<_>16 16 4 8 2.<_><_>0 8 8 16 -1.<_>0 8 4 8 2.<_>4 16 4 8 2.<_><_>8 12 8 10 -1.<_>8 17 8 5 2.<_><_>5 7 5 8 -1.<_>5 11 5 4 2.<_><_>4 1 19 2 -1.<_>4 2 19 1 2.<_><_>0 12 24 9 -1.<_>8 12 8 9 3.<_><_>6 0 13 8 -1.<_>6 4 13 4 2.<_><_>0 0 24 3 -1.<_>0 1 24 1 3.<_><_>20 3 4 11 -1.<_>20 3 2 11 2.<_><_>8 6 6 9 -1.<_>10 6 2 9 3.<_><_>6 11 12 8 -1.<_>12 11 6 4 2.<_>6 15 6 4 2.<_><_>0 8 12 6 -1.<_>0 8 6 3 2.<_>6 11 6 3 2.<_><_>6 17 18 3 -1.<_>6 18 18 1 3.<_><_>0 14 9 6 -1.<_>0 16 9 2 3.<_><_>20 3 4 9 -1.<_>20 3 2 9 2.<_><_>0 3 4 9 -1.<_>2 3 2 9 2.<_><_>15 0 9 19 -1.<_>18 0 3 19 3.<_><_>0 0 9 19 -1.<_>3 0 3 19 3.<_><_>13 11 6 8 -1.<_>13 11 3 8 2.<_><_>5 11 6 8 -1.<_>8 11 3 8 2.<_><_>5 11 19 3 -1.<_>5 12 19 1 3.<_><_>3 20 18 4 -1.<_>9 20 6 4 3.<_><_>6 6 16 6 -1.<_>6 8 16 2 3.<_><_>6 0 9 6 -1.<_>9 0 3 6 3.<_><_>10 3 4 14 -1.<_>10 10 4 7 2.<_><_>1 5 15 12 -1.<_>1 11 15 6 2.<_><_>11 12 8 5 -1.<_>11 12 4 5 2.<_><_>5 0 6 9 -1.<_>7 0 2 9 3.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>5 5 12 8 -1.<_>5 5 6 4 2.<_>11 9 6 4 2.<_><_>13 12 11 6 -1.<_>13 14 11 2 3.<_><_>0 13 21 3 -1.<_>0 14 21 1 3.<_><_>8 1 8 12 -1.<_>12 1 4 6 2.<_>8 7 4 6 2.<_><_>1 0 6 12 -1.<_>1 0 3 6 2.<_>4 6 3 6 2.<_><_>2 2 21 2 -1.<_>2 3 21 1 2.<_><_>2 2 19 3 -1.<_>2 3 19 1 3.<_><_>17 10 6 14 -1.<_>20 10 3 7 2.<_>17 17 3 7 2.<_><_>1 10 6 14 -1.<_>1 10 3 7 2.<_>4 17 3 7 2.<_><_>7 6 14 14 -1.<_>14 6 7 7 2.<_>7 13 7 7 2.<_><_>0 12 9 6 -1.<_>0 14 9 2 3.<_><_>15 14 8 9 -1.<_>15 17 8 3 3.<_><_>1 1 22 4 -1.<_>1 1 11 2 2.<_>12 3 11 2 2.<_><_>9 11 9 6 -1.<_>9 13 9 2 3.<_><_>0 15 18 3 -1.<_>0 16 18 1 3.<_><_>16 14 7 9 -1.<_>16 17 7 3 3.<_><_>4 3 16 4 -1.<_>12 3 8 4 2.<_><_>7 6 12 5 -1.<_>7 6 6 5 2.<_><_>9 6 4 9 -1.<_>11 6 2 9 2.<_><_>12 1 4 10 -1.<_>12 1 2 10 2.<_><_>8 1 4 10 -1.<_>10 1 2 10 2.<_><_>15 15 6 9 -1.<_>15 18 6 3 3.<_><_>3 15 6 9 -1.<_>3 18 6 3 3.<_><_>15 1 3 19 -1.<_>16 1 1 19 3.<_><_>1 3 6 9 -1.<_>3 3 2 9 3.<_><_>15 0 3 19 -1.<_>16 0 1 19 3.<_><_>6 3 12 4 -1.<_>12 3 6 4 2.<_><_>10 5 4 9 -1.<_>10 5 2 9 2.<_><_>6 0 3 19 -1.<_>7 0 1 19 3.<_><_>11 1 3 12 -1.<_>11 7 3 6 2.<_><_>6 7 10 5 -1.<_>11 7 5 5 2.<_><_>11 3 3 18 -1.<_>12 3 1 18 3.<_><_>9 3 6 12 -1.<_>11 3 2 12 3.<_><_>3 7 19 3 -1.<_>3 8 19 1 3.<_><_>2 7 18 3 -1.<_>2 8 18 1 3.<_><_>3 13 18 4 -1.<_>12 13 9 2 2.<_>3 15 9 2 2.<_><_>3 5 6 9 -1.<_>5 5 2 9 3.<_><_>4 1 20 4 -1.<_>14 1 10 2 2.<_>4 3 10 2 2.<_><_>0 1 20 4 -1.<_>0 1 10 2 2.<_>10 3 10 2 2.<_><_>10 15 6 6 -1.<_>10 15 3 6 2.<_><_>0 2 24 8 -1.<_>8 2 8 8 3.<_><_>5 5 18 3 -1.<_>5 6 18 1 3.<_><_>8 15 6 6 -1.<_>11 15 3 6 2.<_><_>11 12 8 5 -1.<_>11 12 4 5 2.<_><_>5 12 8 5 -1.<_>9 12 4 5 2.<_><_>5 0 14 6 -1.<_>5 2 14 2 3.<_><_>10 2 4 15 -1.<_>10 7 4 5 3.<_><_>10 7 5 12 -1.<_>10 11 5 4 3.<_><_>7 9 8 14 -1.<_>7 9 4 7 2.<_>11 16 4 7 2.<_><_>1 5 22 6 -1.<_>12 5 11 3 2.<_>1 8 11 3 2.<_><_>0 5 6 6 -1.<_>0 8 6 3 2.<_><_>12 17 9 4 -1.<_>12 19 9 2 2.<_><_>2 18 19 3 -1.<_>2 19 19 1 3.<_><_>12 17 9 4 -1.<_>12 19 9 2 2.<_><_>1 17 18 3 -1.<_>1 18 18 1 3.<_><_>12 17 9 4 -1.<_>12 19 9 2 2.<_><_>0 0 24 3 -1.<_>0 1 24 1 3.<_><_>5 0 14 4 -1.<_>5 2 14 2 2.<_><_>6 14 9 6 -1.<_>6 16 9 2 3.<_><_>14 13 6 9 -1.<_>14 16 6 3 3.<_><_>5 20 13 4 -1.<_>5 22 13 2 2.<_><_>9 9 6 12 -1.<_>9 13 6 4 3.<_><_>1 10 21 3 -1.<_>8 10 7 3 3.<_><_>8 8 9 6 -1.<_>11 8 3 6 3.<_><_>3 10 9 7 -1.<_>6 10 3 7 3.<_><_>12 10 10 8 -1.<_>17 10 5 4 2.<_>12 14 5 4 2.<_><_>0 15 24 3 -1.<_>8 15 8 3 3.<_><_>8 5 9 6 -1.<_>8 7 9 2 3.<_><_>4 13 6 9 -1.<_>4 16 6 3 3.<_><_>12 17 9 4 -1.<_>12 19 9 2 2.<_><_>9 12 6 6 -1.<_>9 15 6 3 2.<_><_>9 9 14 10 -1.<_>16 9 7 5 2.<_>9 14 7 5 2.<_><_>1 9 14 10 -1.<_>1 9 7 5 2.<_>8 14 7 5 2.<_><_>8 7 9 17 -1.<_>11 7 3 17 3.<_><_>3 4 6 20 -1.<_>3 4 3 10 2.<_>6 14 3 10 2.<_><_>7 8 10 4 -1.<_>7 8 5 4 2.<_><_>10 7 4 9 -1.<_>12 7 2 9 2.<_><_>10 15 6 9 -1.<_>12 15 2 9 3.<_><_>3 8 6 16 -1.<_>3 8 3 8 2.<_>6 16 3 8 2.<_><_>12 17 9 4 -1.<_>12 19 9 2 2.<_><_>3 17 9 4 -1.<_>3 19 9 2 2.<_><_>10 1 9 6 -1.<_>13 1 3 6 3.<_><_>5 7 4 10 -1.<_>5 12 4 5 2.<_><_>7 5 12 6 -1.<_>11 5 4 6 3.<_><_>6 4 9 8 -1.<_>9 4 3 8 3.<_><_>12 16 10 8 -1.<_>17 16 5 4 2.<_>12 20 5 4 2.<_><_>2 16 10 8 -1.<_>2 16 5 4 2.<_>7 20 5 4 2.<_><_>0 0 24 4 -1.<_>12 0 12 2 2.<_>0 2 12 2 2.<_><_>0 6 9 6 -1.<_>0 8 9 2 3.<_><_>0 4 24 6 -1.<_>12 4 12 3 2.<_>0 7 12 3 2.<_><_>5 0 11 4 -1.<_>5 2 11 2 2.<_><_>1 1 22 4 -1.<_>12 1 11 2 2.<_>1 3 11 2 2.<_><_>9 6 6 18 -1.<_>9 15 6 9 2.<_><_>2 9 20 4 -1.<_>2 11 20 2 2.<_><_>5 2 14 14 -1.<_>5 9 14 7 2.<_><_>4 2 16 6 -1.<_>4 5 16 3 2.<_><_>2 3 19 3 -1.<_>2 4 19 1 3.<_><_>7 1 10 4 -1.<_>7 3 10 2 2.<_><_>0 9 4 15 -1.<_>0 14 4 5 3.<_><_>2 10 21 3 -1.<_>2 11 21 1 3.<_><_>3 0 6 6 -1.<_>6 0 3 6 2.<_><_>6 4 14 9 -1.<_>6 7 14 3 3.<_><_>9 1 6 9 -1.<_>11 1 2 9 3.<_><_>15 8 9 9 -1.<_>15 11 9 3 3.<_><_>8 0 4 21 -1.<_>8 7 4 7 3.<_><_>3 22 19 2 -1.<_>3 23 19 1 2.<_><_>2 15 20 3 -1.<_>2 16 20 1 3.<_><_>19 0 4 13 -1.<_>19 0 2 13 2.<_><_>1 7 8 8 -1.<_>1 11 8 4 2.<_><_>14 14 6 9 -1.<_>14 17 6 3 3.<_><_>4 14 6 9 -1.<_>4 17 6 3 3.<_><_>14 5 4 10 -1.<_>14 5 2 10 2.<_><_>6 5 4 10 -1.<_>8 5 2 10 2.<_><_>14 5 6 6 -1.<_>14 8 6 3 2.<_><_>4 5 6 6 -1.<_>4 8 6 3 2.<_><_>0 2 24 21 -1.<_>8 2 8 21 3.<_><_>1 2 6 13 -1.<_>3 2 2 13 3.<_><_>20 0 4 21 -1.<_>20 0 2 21 2.<_><_>0 4 4 20 -1.<_>2 4 2 20 2.<_><_>8 16 9 6 -1.<_>8 18 9 2 3.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>16 12 7 9 -1.<_>16 15 7 3 3.<_><_>5 21 14 3 -1.<_>12 21 7 3 2.<_><_>11 5 6 9 -1.<_>11 5 3 9 2.<_><_>10 5 4 10 -1.<_>12 5 2 10 2.<_><_>10 6 6 9 -1.<_>12 6 2 9 3.<_><_>7 5 6 9 -1.<_>10 5 3 9 2.<_><_>14 14 10 4 -1.<_>14 16 10 2 2.<_><_>5 5 14 14 -1.<_>5 5 7 7 2.<_>12 12 7 7 2.<_><_>12 8 12 6 -1.<_>18 8 6 3 2.<_>12 11 6 3 2.<_><_>6 6 12 12 -1.<_>6 6 6 6 2.<_>12 12 6 6 2.<_><_>11 13 6 10 -1.<_>13 13 2 10 3.<_><_>1 10 20 8 -1.<_>1 10 10 4 2.<_>11 14 10 4 2.<_><_>15 13 9 6 -1.<_>15 15 9 2 3.<_><_>9 0 6 9 -1.<_>9 3 6 3 3.<_><_>10 1 5 14 -1.<_>10 8 5 7 2.<_><_>3 4 16 6 -1.<_>3 6 16 2 3.<_><_>16 3 8 9 -1.<_>16 6 8 3 3.<_><_>7 13 6 10 -1.<_>9 13 2 10 3.<_><_>15 13 9 6 -1.<_>15 15 9 2 3.<_><_>0 13 9 6 -1.<_>0 15 9 2 3.<_><_>13 16 9 6 -1.<_>13 18 9 2 3.<_><_>2 16 9 6 -1.<_>2 18 9 2 3.<_><_>5 16 18 3 -1.<_>5 17 18 1 3.<_><_>1 16 18 3 -1.<_>1 17 18 1 3.<_><_>5 0 18 3 -1.<_>5 1 18 1 3.<_><_>1 1 19 2 -1.<_>1 2 19 1 2.<_><_>14 2 6 11 -1.<_>16 2 2 11 3.<_><_>4 15 15 6 -1.<_>9 15 5 6 3.<_><_>14 2 6 11 -1.<_>16 2 2 11 3.<_><_>4 2 6 11 -1.<_>6 2 2 11 3.<_><_>18 2 6 9 -1.<_>18 5 6 3 3.<_><_>1 2 22 4 -1.<_>1 2 11 2 2.<_>12 4 11 2 2.<_><_>2 0 21 12 -1.<_>9 0 7 12 3.<_><_>0 12 18 3 -1.<_>0 13 18 1 3.<_><_>12 2 6 9 -1.<_>14 2 2 9 3.<_><_>3 10 18 3 -1.<_>3 11 18 1 3.<_><_>16 3 8 9 -1.<_>16 6 8 3 3.<_><_>3 7 18 3 -1.<_>3 8 18 1 3.<_><_>9 11 6 9 -1.<_>11 11 2 9 3.<_><_>9 8 6 9 -1.<_>11 8 2 9 3.<_><_>15 0 2 18 -1.<_>15 0 1 18 2.<_><_>7 0 2 18 -1.<_>8 0 1 18 2.<_><_>17 3 7 9 -1.<_>17 6 7 3 3.<_><_>3 18 9 6 -1.<_>3 20 9 2 3.<_><_>3 18 21 3 -1.<_>3 19 21 1 3.<_><_>0 3 7 9 -1.<_>0 6 7 3 3.<_><_>2 7 22 3 -1.<_>2 8 22 1 3.<_><_>0 3 24 16 -1.<_>0 3 12 8 2.<_>12 11 12 8 2.<_><_>13 17 9 4 -1.<_>13 19 9 2 2.<_><_>5 5 12 8 -1.<_>5 5 6 4 2.<_>11 9 6 4 2.<_><_>5 6 14 6 -1.<_>12 6 7 3 2.<_>5 9 7 3 2.<_><_>5 16 14 6 -1.<_>5 16 7 3 2.<_>12 19 7 3 2.<_><_>18 2 6 9 -1.<_>18 5 6 3 3.<_><_>0 2 6 9 -1.<_>0 5 6 3 3.<_><_>3 4 20 10 -1.<_>13 4 10 5 2.<_>3 9 10 5 2.<_><_>2 13 9 8 -1.<_>5 13 3 8 3.<_><_>2 1 21 15 -1.<_>9 1 7 15 3.<_><_>5 12 14 8 -1.<_>12 12 7 8 2.<_><_>6 7 12 4 -1.<_>6 7 6 4 2.<_><_>6 5 9 6 -1.<_>9 5 3 6 3.<_><_>13 11 6 6 -1.<_>13 11 3 6 2.<_><_>5 11 6 6 -1.<_>8 11 3 6 2.<_><_>6 4 18 2 -1.<_>6 5 18 1 2.<_><_>0 2 6 11 -1.<_>2 2 2 11 3.<_><_>18 0 6 15 -1.<_>20 0 2 15 3.<_><_>0 0 6 13 -1.<_>2 0 2 13 3.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>6 0 6 9 -1.<_>8 0 2 9 3.<_><_>0 2 24 4 -1.<_>8 2 8 4 3.<_><_>3 13 18 4 -1.<_>12 13 9 4 2.<_><_>9 7 10 4 -1.<_>9 7 5 4 2.<_><_>5 8 12 3 -1.<_>11 8 6 3 2.<_><_>4 14 19 3 -1.<_>4 15 19 1 3.<_><_>10 0 4 20 -1.<_>10 10 4 10 2.<_><_>8 15 9 6 -1.<_>8 17 9 2 3.<_><_>2 9 15 4 -1.<_>7 9 5 4 3.<_><_>8 4 12 7 -1.<_>12 4 4 7 3.<_><_>0 10 6 9 -1.<_>0 13 6 3 3.<_><_>18 5 6 9 -1.<_>18 8 6 3 3.<_><_>0 18 16 6 -1.<_>0 18 8 3 2.<_>8 21 8 3 2.<_><_>9 18 14 6 -1.<_>16 18 7 3 2.<_>9 21 7 3 2.<_><_>1 20 20 4 -1.<_>1 20 10 2 2.<_>11 22 10 2 2.<_><_>2 8 20 6 -1.<_>12 8 10 3 2.<_>2 11 10 3 2.<_><_>7 8 6 9 -1.<_>9 8 2 9 3.<_><_>8 5 12 8 -1.<_>12 5 4 8 3.<_><_>4 5 12 8 -1.<_>8 5 4 8 3.<_><_>10 6 6 9 -1.<_>12 6 2 9 3.<_><_>2 0 6 16 -1.<_>4 0 2 16 3.<_><_>15 4 6 12 -1.<_>15 8 6 4 3.<_><_>3 4 6 12 -1.<_>3 8 6 4 3.<_><_>15 12 9 6 -1.<_>15 14 9 2 3.<_><_>4 0 15 22 -1.<_>4 11 15 11 2.<_><_>15 12 9 6 -1.<_>15 14 9 2 3.<_><_>0 12 9 6 -1.<_>0 14 9 2 3.<_><_>15 15 9 6 -1.<_>15 17 9 2 3.<_><_>0 15 9 6 -1.<_>0 17 9 2 3.<_><_>10 0 8 10 -1.<_>14 0 4 5 2.<_>10 5 4 5 2.<_><_>1 0 4 16 -1.<_>3 0 2 16 2.<_><_>7 6 10 6 -1.<_>7 8 10 2 3.<_><_>10 12 4 10 -1.<_>10 17 4 5 2.<_><_>8 4 10 6 -1.<_>8 6 10 2 3.<_><_>3 22 18 2 -1.<_>12 22 9 2 2.<_><_>7 7 11 6 -1.<_>7 9 11 2 3.<_><_>0 0 12 10 -1.<_>0 0 6 5 2.<_>6 5 6 5 2.<_><_>10 1 12 6 -1.<_>16 1 6 3 2.<_>10 4 6 3 2.<_><_>7 16 9 4 -1.<_>7 18 9 2 2.<_><_>5 7 15 16 -1.<_>10 7 5 16 3.<_><_>5 10 12 13 -1.<_>11 10 6 13 2.<_><_>6 2 12 6 -1.<_>12 2 6 3 2.<_>6 5 6 3 2.<_><_>3 9 12 9 -1.<_>3 12 12 3 3.<_><_>16 2 8 6 -1.<_>16 5 8 3 2.<_><_>0 2 8 6 -1.<_>0 5 8 3 2.<_><_>0 3 24 11 -1.<_>0 3 12 11 2.<_><_>0 13 8 10 -1.<_>0 13 4 5 2.<_>4 18 4 5 2.<_><_>10 14 4 10 -1.<_>10 19 4 5 2.<_><_>10 2 4 21 -1.<_>10 9 4 7 3.<_><_>4 4 15 9 -1.<_>4 7 15 3 3.<_><_>0 1 24 6 -1.<_>8 1 8 6 3.<_><_>9 6 5 16 -1.<_>9 14 5 8 2.<_><_>3 21 18 3 -1.<_>9 21 6 3 3.<_><_>6 5 3 12 -1.<_>6 11 3 6 2.<_><_>11 6 4 9 -1.<_>11 6 2 9 2.<_><_>5 6 9 8 -1.<_>8 6 3 8 3.<_><_>4 3 20 2 -1.<_>4 4 20 1 2.<_><_>2 10 18 3 -1.<_>8 10 6 3 3.<_><_>7 15 10 6 -1.<_>7 17 10 2 3.<_><_>1 4 4 18 -1.<_>1 4 2 9 2.<_>3 13 2 9 2.<_><_>13 0 6 9 -1.<_>15 0 2 9 3.<_><_>5 0 6 9 -1.<_>7 0 2 9 3.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>6 7 9 6 -1.<_>9 7 3 6 3.<_><_>3 0 18 2 -1.<_>3 1 18 1 2.<_><_>0 10 20 4 -1.<_>0 10 10 2 2.<_>10 12 10 2 2.<_><_>10 2 4 12 -1.<_>10 8 4 6 2.<_><_>6 5 6 12 -1.<_>6 5 3 6 2.<_>9 11 3 6 2.<_><_>6 0 18 22 -1.<_>15 0 9 11 2.<_>6 11 9 11 2.<_><_>0 0 18 22 -1.<_>0 0 9 11 2.<_>9 11 9 11 2.<_><_>18 2 6 11 -1.<_>20 2 2 11 3.<_><_>0 2 6 11 -1.<_>2 2 2 11 3.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>0 0 20 3 -1.<_>0 1 20 1 3.<_><_>2 2 20 2 -1.<_>2 3 20 1 2.<_><_>1 10 18 2 -1.<_>1 11 18 1 2.<_><_>18 7 6 9 -1.<_>18 10 6 3 3.<_><_>0 0 22 9 -1.<_>0 3 22 3 3.<_><_>17 3 6 9 -1.<_>17 6 6 3 3.<_><_>0 7 6 9 -1.<_>0 10 6 3 3.<_><_>0 6 24 6 -1.<_>0 8 24 2 3.<_><_>0 2 6 10 -1.<_>2 2 2 10 3.<_><_>10 6 6 9 -1.<_>12 6 2 9 3.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>15 0 6 9 -1.<_>17 0 2 9 3.<_><_>3 0 6 9 -1.<_>5 0 2 9 3.<_><_>15 17 9 6 -1.<_>15 19 9 2 3.<_><_>0 17 18 3 -1.<_>0 18 18 1 3.<_><_>15 14 9 6 -1.<_>15 16 9 2 3.<_><_>0 15 23 6 -1.<_>0 17 23 2 3.<_><_>5 15 18 3 -1.<_>5 16 18 1 3.<_><_>0 14 9 6 -1.<_>0 16 9 2 3.<_><_>9 8 8 10 -1.<_>13 8 4 5 2.<_>9 13 4 5 2.<_><_>3 7 15 6 -1.<_>8 7 5 6 3.<_><_>9 8 8 10 -1.<_>13 8 4 5 2.<_>9 13 4 5 2.<_><_>5 0 6 12 -1.<_>8 0 3 12 2.<_><_>9 8 8 10 -1.<_>13 8 4 5 2.<_>9 13 4 5 2.<_><_>8 5 6 9 -1.<_>10 5 2 9 3.<_><_>10 6 4 18 -1.<_>12 6 2 9 2.<_>10 15 2 9 2.<_><_>5 7 12 4 -1.<_>11 7 6 4 2.<_><_>9 8 8 10 -1.<_>13 8 4 5 2.<_>9 13 4 5 2.<_><_>7 8 8 10 -1.<_>7 8 4 5 2.<_>11 13 4 5 2.<_><_>11 10 6 14 -1.<_>14 10 3 7 2.<_>11 17 3 7 2.<_><_>9 5 6 19 -1.<_>12 5 3 19 2.<_><_>6 12 12 6 -1.<_>12 12 6 3 2.<_>6 15 6 3 2.<_><_>1 9 18 6 -1.<_>1 9 9 3 2.<_>10 12 9 3 2.<_><_>16 14 8 10 -1.<_>20 14 4 5 2.<_>16 19 4 5 2.<_><_>0 9 22 8 -1.<_>0 9 11 4 2.<_>11 13 11 4 2.<_><_>8 18 12 6 -1.<_>14 18 6 3 2.<_>8 21 6 3 2.<_><_>0 6 20 18 -1.<_>0 6 10 9 2.<_>10 15 10 9 2.<_><_>3 6 20 12 -1.<_>13 6 10 6 2.<_>3 12 10 6 2.<_><_>0 16 10 8 -1.<_>0 16 5 4 2.<_>5 20 5 4 2.<_><_>6 16 18 3 -1.<_>6 17 18 1 3.<_><_>0 11 19 3 -1.<_>0 12 19 1 3.<_><_>14 6 6 9 -1.<_>14 9 6 3 3.<_><_>1 7 22 4 -1.<_>1 7 11 2 2.<_>12 9 11 2 2.<_><_>13 6 7 12 -1.<_>13 10 7 4 3.<_><_>4 7 11 9 -1.<_>4 10 11 3 3.<_><_>12 10 10 8 -1.<_>17 10 5 4 2.<_>12 14 5 4 2.<_><_>2 12 9 7 -1.<_>5 12 3 7 3.<_><_>16 14 6 9 -1.<_>16 17 6 3 3.<_><_>3 12 6 12 -1.<_>3 16 6 4 3.<_><_>14 13 6 6 -1.<_>14 16 6 3 2.<_><_>8 0 6 9 -1.<_>10 0 2 9 3.<_><_>9 1 6 23 -1.<_>11 1 2 23 3.<_><_>0 16 9 6 -1.<_>0 18 9 2 3.<_><_>4 17 18 3 -1.<_>4 18 18 1 3.<_><_>5 2 13 14 -1.<_>5 9 13 7 2.<_><_>15 0 8 12 -1.<_>19 0 4 6 2.<_>15 6 4 6 2.<_><_>0 0 8 12 -1.<_>0 0 4 6 2.<_>4 6 4 6 2.<_><_>8 2 8 7 -1.<_>8 2 4 7 2.<_><_>1 1 6 9 -1.<_>3 1 2 9 3.<_><_>14 8 6 12 -1.<_>17 8 3 6 2.<_>14 14 3 6 2.<_><_>4 8 6 12 -1.<_>4 8 3 6 2.<_>7 14 3 6 2.<_><_>16 5 5 15 -1.<_>16 10 5 5 3.<_><_>3 5 5 15 -1.<_>3 10 5 5 3.<_><_>18 4 6 9 -1.<_>18 7 6 3 3.<_><_>1 7 6 15 -1.<_>1 12 6 5 3.<_><_>11 15 12 8 -1.<_>17 15 6 4 2.<_>11 19 6 4 2.<_><_>0 2 24 4 -1.<_>0 2 12 2 2.<_>12 4 12 2 2.<_><_>15 1 2 19 -1.<_>15 1 1 19 2.<_><_>7 1 2 19 -1.<_>8 1 1 19 2.<_><_>22 1 2 20 -1.<_>22 1 1 20 2.<_><_>0 1 2 20 -1.<_>1 1 1 20 2.<_><_>18 11 6 12 -1.<_>20 11 2 12 3.<_><_>0 11 6 12 -1.<_>2 11 2 12 3.<_><_>3 6 18 14 -1.<_>3 13 18 7 2.<_><_>6 10 7 8 -1.<_>6 14 7 4 2.<_><_>7 9 12 12 -1.<_>7 13 12 4 3.<_><_>2 18 18 5 -1.<_>11 18 9 5 2.<_><_>4 21 20 3 -1.<_>4 22 20 1 3.<_><_>9 12 6 12 -1.<_>9 12 3 6 2.<_>12 18 3 6 2.<_><_>4 6 18 3 -1.<_>4 7 18 1 3.<_><_>3 6 18 3 -1.<_>3 7 18 1 3.<_><_>18 4 6 9 -1.<_>18 7 6 3 3.<_><_>2 12 9 6 -1.<_>2 14 9 2 3.<_><_>4 14 18 4 -1.<_>13 14 9 2 2.<_>4 16 9 2 2.<_><_>7 7 6 14 -1.<_>7 7 3 7 2.<_>10 14 3 7 2.<_><_>7 13 12 6 -1.<_>13 13 6 3 2.<_>7 16 6 3 2.<_><_>6 7 12 9 -1.<_>10 7 4 9 3.<_><_>12 12 6 6 -1.<_>12 12 3 6 2.<_><_>0 2 4 10 -1.<_>0 7 4 5 2.<_><_>8 0 9 6 -1.<_>11 0 3 6 3.<_><_>2 9 12 6 -1.<_>2 12 12 3 2.<_><_>13 10 6 9 -1.<_>13 13 6 3 3.<_><_>5 10 6 9 -1.<_>5 13 6 3 3.<_><_>9 15 9 6 -1.<_>9 17 9 2 3.<_><_>5 16 12 6 -1.<_>5 19 12 3 2.<_><_>3 2 20 3 -1.<_>3 3 20 1 3.<_><_>2 5 12 6 -1.<_>6 5 4 6 3.<_><_>11 0 3 24 -1.<_>12 0 1 24 3.<_><_>3 16 15 4 -1.<_>8 16 5 4 3.<_><_>9 12 6 12 -1.<_>9 18 6 6 2.<_><_>1 15 12 8 -1.<_>1 15 6 4 2.<_>7 19 6 4 2.<_><_>15 10 8 14 -1.<_>19 10 4 7 2.<_>15 17 4 7 2.<_><_>1 9 8 14 -1.<_>1 9 4 7 2.<_>5 16 4 7 2.<_><_>9 11 9 10 -1.<_>9 16 9 5 2.<_><_>6 7 12 6 -1.<_>6 9 12 2 3.<_><_>10 15 6 9 -1.<_>12 15 2 9 3.<_><_>7 8 9 7 -1.<_>10 8 3 7 3.<_><_>10 4 8 10 -1.<_>14 4 4 5 2.<_>10 9 4 5 2.<_><_>4 6 6 9 -1.<_>4 9 6 3 3.<_><_>0 6 24 12 -1.<_>8 6 8 12 3.<_><_>3 7 6 14 -1.<_>6 7 3 14 2.<_><_>19 8 5 8 -1.<_>19 12 5 4 2.<_><_>0 8 5 8 -1.<_>0 12 5 4 2.<_><_>17 3 6 6 -1.<_>17 6 6 3 2.<_><_>1 3 6 6 -1.<_>1 6 6 3 2.<_><_>18 2 6 9 -1.<_>18 5 6 3 3.<_><_>0 2 6 9 -1.<_>0 5 6 3 3.<_><_>3 3 18 6 -1.<_>3 5 18 2 3.<_><_>2 3 9 6 -1.<_>2 5 9 2 3.<_><_>9 3 10 8 -1.<_>14 3 5 4 2.<_>9 7 5 4 2.<_><_>5 3 10 8 -1.<_>5 3 5 4 2.<_>10 7 5 4 2.<_><_>10 11 6 12 -1.<_>10 11 3 12 2.<_><_>8 11 6 11 -1.<_>11 11 3 11 2.<_><_>7 8 10 4 -1.<_>7 8 5 4 2.<_><_>9 6 6 7 -1.<_>12 6 3 7 2.<_><_>5 18 18 3 -1.<_>5 19 18 1 3.<_><_>8 4 6 9 -1.<_>10 4 2 9 3.<_><_>8 1 9 7 -1.<_>11 1 3 7 3.<_><_>6 11 6 6 -1.<_>9 11 3 6 2.<_><_>14 12 4 11 -1.<_>14 12 2 11 2.<_><_>6 12 4 11 -1.<_>8 12 2 11 2.<_><_>8 0 12 18 -1.<_>12 0 4 18 3.<_><_>2 12 10 5 -1.<_>7 12 5 5 2.<_><_>2 20 22 3 -1.<_>2 21 22 1 3.<_><_>0 4 2 20 -1.<_>1 4 1 20 2.<_><_>0 2 24 4 -1.<_>8 2 8 4 3.<_><_>7 8 10 4 -1.<_>7 10 10 2 2.<_><_>6 7 8 10 -1.<_>6 7 4 5 2.<_>10 12 4 5 2.<_><_>14 0 6 14 -1.<_>17 0 3 7 2.<_>14 7 3 7 2.<_><_>4 11 5 8 -1.<_>4 15 5 4 2.<_><_>2 0 20 9 -1.<_>2 3 20 3 3.<_><_>6 7 12 8 -1.<_>6 7 6 4 2.<_>12 11 6 4 2.<_><_>9 17 6 6 -1.<_>9 20 6 3 2.<_><_>7 10 10 4 -1.<_>7 12 10 2 2.<_><_>6 5 12 9 -1.<_>10 5 4 9 3.<_><_>5 11 6 8 -1.<_>8 11 3 8 2.<_><_>18 4 4 17 -1.<_>18 4 2 17 2.<_><_>0 0 6 6 -1.<_>3 0 3 6 2.<_><_>18 4 4 17 -1.<_>18 4 2 17 2.<_><_>2 4 4 17 -1.<_>4 4 2 17 2.<_><_>5 18 19 3 -1.<_>5 19 19 1 3.<_><_>11 0 2 18 -1.<_>11 9 2 9 2.<_><_>15 4 2 18 -1.<_>15 13 2 9 2.<_><_>7 4 2 18 -1.<_>7 13 2 9 2.<_><_>7 11 10 8 -1.<_>12 11 5 4 2.<_>7 15 5 4 2.<_><_>10 6 4 9 -1.<_>12 6 2 9 2.<_><_>10 0 6 9 -1.<_>12 0 2 9 3.<_><_>2 9 16 8 -1.<_>2 9 8 4 2.<_>10 13 8 4 2.<_><_>14 15 6 9 -1.<_>14 18 6 3 3.<_><_>8 7 6 9 -1.<_>10 7 2 9 3.<_><_>14 15 6 9 -1.<_>14 18 6 3 3.<_><_>3 12 12 6 -1.<_>3 14 12 2 3.<_><_>14 12 9 6 -1.<_>14 14 9 2 3.<_><_>1 12 9 6 -1.<_>1 14 9 2 3.<_><_>3 7 18 3 -1.<_>3 8 18 1 3.<_><_>1 7 22 6 -1.<_>1 9 22 2 3.<_><_>18 4 6 6 -1.<_>18 7 6 3 2.<_><_>0 4 6 6 -1.<_>0 7 6 3 2.<_><_>5 11 16 6 -1.<_>5 14 16 3 2.<_><_>6 16 9 4 -1.<_>6 18 9 2 2.<_><_>14 15 6 9 -1.<_>14 18 6 3 3.<_><_>4 15 6 9 -1.<_>4 18 6 3 3.<_><_>15 1 6 23 -1.<_>17 1 2 23 3.<_><_>0 21 24 3 -1.<_>8 21 8 3 3.<_><_>0 20 24 4 -1.<_>8 20 8 4 3.<_><_>3 1 6 23 -1.<_>5 1 2 23 3.<_><_>3 17 18 3 -1.<_>3 18 18 1 3.<_><_>0 16 18 3 -1.<_>0 17 18 1 3.<_><_>1 16 22 4 -1.<_>12 16 11 2 2.<_>1 18 11 2 2.<_><_>0 16 9 6 -1.<_>0 18 9 2 3.<_><_>2 10 21 3 -1.<_>9 10 7 3 3.<_><_>2 18 12 6 -1.<_>2 18 6 3 2.<_>8 21 6 3 2.<_><_>0 5 24 4 -1.<_>0 7 24 2 2.<_><_>10 2 4 15 -1.<_>10 7 4 5 3.<_><_>10 7 6 12 -1.<_>10 13 6 6 2.<_><_>6 6 6 9 -1.<_>8 6 2 9 3.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>9 7 6 9 -1.<_>11 7 2 9 3.<_><_>2 1 20 3 -1.<_>2 2 20 1 3.<_><_>1 18 12 6 -1.<_>1 18 6 3 2.<_>7 21 6 3 2.<_><_>13 2 4 13 -1.<_>13 2 2 13 2.<_><_>6 7 12 4 -1.<_>12 7 6 4 2.<_><_>10 1 4 13 -1.<_>10 1 2 13 2.<_><_>6 0 3 18 -1.<_>7 0 1 18 3.<_><_>14 3 10 5 -1.<_>14 3 5 5 2.<_><_>6 15 12 8 -1.<_>10 15 4 8 3.<_><_>9 10 6 9 -1.<_>11 10 2 9 3.<_><_>8 3 4 9 -1.<_>10 3 2 9 2.<_><_>17 0 6 14 -1.<_>20 0 3 7 2.<_>17 7 3 7 2.<_><_>1 0 6 14 -1.<_>1 0 3 7 2.<_>4 7 3 7 2.<_><_>14 0 6 16 -1.<_>17 0 3 8 2.<_>14 8 3 8 2.<_><_>7 4 4 10 -1.<_>9 4 2 10 2.<_><_>3 17 18 6 -1.<_>12 17 9 3 2.<_>3 20 9 3 2.<_><_>1 20 22 4 -1.<_>12 20 11 4 2.<_><_>14 3 10 5 -1.<_>14 3 5 5 2.<_><_>0 3 10 5 -1.<_>5 3 5 5 2.<_><_>12 6 12 16 -1.<_>16 6 4 16 3.<_><_>0 6 12 16 -1.<_>4 6 4 16 3.<_><_>10 9 5 15 -1.<_>10 14 5 5 3.<_><_>1 18 21 2 -1.<_>1 19 21 1 2.<_><_>15 0 9 6 -1.<_>15 2 9 2 3.<_><_>6 1 12 4 -1.<_>12 1 6 4 2.<_><_>6 0 12 12 -1.<_>12 0 6 6 2.<_>6 6 6 6 2.<_><_>8 10 8 12 -1.<_>8 10 4 6 2.<_>12 16 4 6 2.<_><_>14 16 10 8 -1.<_>19 16 5 4 2.<_>14 20 5 4 2.<_><_>0 16 10 8 -1.<_>0 16 5 4 2.<_>5 20 5 4 2.<_><_>10 12 12 5 -1.<_>14 12 4 5 3.<_><_>6 16 10 8 -1.<_>6 16 5 4 2.<_>11 20 5 4 2.<_><_>7 6 12 6 -1.<_>13 6 6 3 2.<_>7 9 6 3 2.<_><_>9 6 4 18 -1.<_>9 6 2 9 2.<_>11 15 2 9 2.<_><_>10 9 6 14 -1.<_>13 9 3 7 2.<_>10 16 3 7 2.<_><_>8 9 6 14 -1.<_>8 9 3 7 2.<_>11 16 3 7 2.<_><_>7 4 11 12 -1.<_>7 10 11 6 2.<_><_>4 8 6 16 -1.<_>4 8 3 8 2.<_>7 16 3 8 2.<_><_>17 3 4 21 -1.<_>17 10 4 7 3.<_><_>3 3 4 21 -1.<_>3 10 4 7 3.<_><_>10 1 8 18 -1.<_>14 1 4 9 2.<_>10 10 4 9 2.<_><_>2 5 16 8 -1.<_>2 5 8 4 2.<_>10 9 8 4 2.<_><_>3 6 18 12 -1.<_>3 10 18 4 3.<_><_>4 10 16 12 -1.<_>4 14 16 4 3.<_><_>15 4 8 20 -1.<_>19 4 4 10 2.<_>15 14 4 10 2.<_><_>7 2 9 6 -1.<_>10 2 3 6 3.<_><_>15 4 8 20 -1.<_>19 4 4 10 2.<_>15 14 4 10 2.<_><_>1 4 8 20 -1.<_>1 4 4 10 2.<_>5 14 4 10 2.<_><_>11 8 8 14 -1.<_>15 8 4 7 2.<_>11 15 4 7 2.<_><_>5 8 8 14 -1.<_>5 8 4 7 2.<_>9 15 4 7 2.<_><_>10 13 5 8 -1.<_>10 17 5 4 2.<_><_>4 13 7 9 -1.<_>4 16 7 3 3.<_><_>0 13 24 10 -1.<_>0 18 24 5 2.<_><_>4 2 8 11 -1.<_>8 2 4 11 2.<_><_>10 2 8 16 -1.<_>14 2 4 8 2.<_>10 10 4 8 2.<_><_>0 2 24 6 -1.<_>0 2 12 3 2.<_>12 5 12 3 2.<_><_>6 0 12 9 -1.<_>6 3 12 3 3.<_><_>1 2 12 12 -1.<_>1 2 6 6 2.<_>7 8 6 6 2.<_><_>18 5 6 9 -1.<_>18 8 6 3 3.<_><_>4 3 8 10 -1.<_>4 3 4 5 2.<_>8 8 4 5 2.<_><_>6 21 18 3 -1.<_>6 22 18 1 3.<_><_>1 10 18 2 -1.<_>1 11 18 1 2.<_><_>1 10 22 3 -1.<_>1 11 22 1 3.<_><_>2 8 12 9 -1.<_>2 11 12 3 3.<_><_>12 8 12 6 -1.<_>18 8 6 3 2.<_>12 11 6 3 2.<_><_>0 8 12 6 -1.<_>0 8 6 3 2.<_>6 11 6 3 2.<_><_>10 15 6 9 -1.<_>12 15 2 9 3.<_><_>7 13 9 6 -1.<_>7 15 9 2 3.<_><_>9 8 7 12 -1.<_>9 14 7 6 2.<_><_>4 13 9 6 -1.<_>7 13 3 6 3.<_><_>6 15 18 4 -1.<_>12 15 6 4 3.<_><_>5 4 4 16 -1.<_>7 4 2 16 2.<_><_>10 15 6 9 -1.<_>12 15 2 9 3.<_><_>8 15 6 9 -1.<_>10 15 2 9 3.<_><_>9 11 12 10 -1.<_>15 11 6 5 2.<_>9 16 6 5 2.<_><_>3 6 14 6 -1.<_>3 8 14 2 3.<_><_>4 2 17 8 -1.<_>4 6 17 4 2.<_><_>6 2 12 21 -1.<_>6 9 12 7 3.<_><_>8 1 9 9 -1.<_>8 4 9 3 3.<_><_>0 7 24 3 -1.<_>12 7 12 3 2.<_><_>11 6 9 10 -1.<_>11 11 9 5 2.<_><_>2 11 18 3 -1.<_>2 12 18 1 3.<_><_>8 16 9 4 -1.<_>8 18 9 2 2.<_><_>0 0 9 6 -1.<_>0 2 9 2 3.<_><_>0 11 24 6 -1.<_>0 13 24 2 3.<_><_>2 9 20 6 -1.<_>2 12 20 3 2.<_><_>4 5 16 12 -1.<_>12 5 8 6 2.<_>4 11 8 6 2.<_><_>10 2 4 15 -1.<_>10 7 4 5 3.<_><_>7 3 10 4 -1.<_>7 5 10 2 2.<_><_>9 15 6 8 -1.<_>9 19 6 4 2.<_><_>17 0 7 10 -1.<_>17 5 7 5 2.<_><_>0 0 7 10 -1.<_>0 5 7 5 2.<_><_>16 1 6 12 -1.<_>19 1 3 6 2.<_>16 7 3 6 2.<_><_>1 0 19 8 -1.<_>1 4 19 4 2.<_><_>12 2 9 4 -1.<_>12 4 9 2 2.<_><_>3 2 9 4 -1.<_>3 4 9 2 2.<_><_>12 2 10 6 -1.<_>12 4 10 2 3.<_><_>3 4 18 2 -1.<_>12 4 9 2 2.<_><_>12 1 4 9 -1.<_>12 1 2 9 2.<_><_>8 1 4 9 -1.<_>10 1 2 9 2.<_><_>10 5 8 10 -1.<_>14 5 4 5 2.<_>10 10 4 5 2.<_><_>6 4 12 13 -1.<_>10 4 4 13 3.<_><_>13 5 6 6 -1.<_>13 5 3 6 2.<_><_>1 5 12 3 -1.<_>7 5 6 3 2.<_><_>7 5 10 6 -1.<_>7 7 10 2 3.<_><_>2 0 21 5 -1.<_>9 0 7 5 3.<_><_>0 8 9 9 -1.<_>0 11 9 3 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>0 3 6 7 -1.<_>3 3 3 7 2.<_><_>9 18 12 6 -1.<_>15 18 6 3 2.<_>9 21 6 3 2.<_><_>2 8 20 6 -1.<_>2 8 10 3 2.<_>12 11 10 3 2.<_><_>13 2 10 4 -1.<_>13 4 10 2 2.<_><_>4 5 5 18 -1.<_>4 11 5 6 3.<_><_>20 4 4 9 -1.<_>20 4 2 9 2.<_><_>8 6 8 14 -1.<_>8 13 8 7 2.<_><_>0 1 24 6 -1.<_>12 1 12 3 2.<_>0 4 12 3 2.<_><_>0 4 4 9 -1.<_>2 4 2 9 2.<_><_>3 6 18 3 -1.<_>3 7 18 1 3.<_><_>3 17 16 6 -1.<_>3 19 16 2 3.<_><_>13 6 6 9 -1.<_>13 9 6 3 3.<_><_>5 6 14 6 -1.<_>5 6 7 3 2.<_>12 9 7 3 2.<_><_>13 5 8 10 -1.<_>17 5 4 5 2.<_>13 10 4 5 2.<_><_>2 2 20 3 -1.<_>2 3 20 1 3.<_><_>9 2 9 6 -1.<_>12 2 3 6 3.<_><_>8 6 6 9 -1.<_>10 6 2 9 3.<_><_>12 3 4 11 -1.<_>12 3 2 11 2.<_><_>8 3 4 11 -1.<_>10 3 2 11 2.<_><_>8 3 8 10 -1.<_>12 3 4 5 2.<_>8 8 4 5 2.<_><_>11 1 2 18 -1.<_>12 1 1 18 2.<_><_>9 2 9 6 -1.<_>12 2 3 6 3.<_><_>0 2 19 3 -1.<_>0 3 19 1 3.<_><_>9 14 9 6 -1.<_>9 16 9 2 3.<_><_>1 8 18 5 -1.<_>7 8 6 5 3.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>6 0 6 9 -1.<_>8 0 2 9 3.<_><_>13 6 4 15 -1.<_>13 11 4 5 3.<_><_>1 5 18 3 -1.<_>1 6 18 1 3.<_><_>9 7 14 6 -1.<_>9 9 14 2 3.<_><_>2 16 18 3 -1.<_>2 17 18 1 3.<_><_>15 17 9 6 -1.<_>15 19 9 2 3.<_><_>0 8 12 6 -1.<_>0 8 6 3 2.<_>6 11 6 3 2.<_><_>9 13 7 8 -1.<_>9 17 7 4 2.<_><_>2 17 20 3 -1.<_>2 18 20 1 3.<_><_>15 17 9 6 -1.<_>15 19 9 2 3.<_><_>4 0 15 4 -1.<_>4 2 15 2 2.<_><_>17 2 6 6 -1.<_>17 5 6 3 2.<_><_>0 3 6 9 -1.<_>0 6 6 3 3.<_><_>15 17 9 6 -1.<_>15 19 9 2 3.<_><_>0 17 9 6 -1.<_>0 19 9 2 3.<_><_>9 18 12 6 -1.<_>15 18 6 3 2.<_>9 21 6 3 2.<_><_>3 15 6 9 -1.<_>3 18 6 3 3.<_><_>16 13 8 10 -1.<_>20 13 4 5 2.<_>16 18 4 5 2.<_><_>0 14 24 4 -1.<_>8 14 8 4 3.<_><_>13 18 6 6 -1.<_>13 18 3 6 2.<_><_>0 13 8 10 -1.<_>0 13 4 5 2.<_>4 18 4 5 2.<_><_>0 14 24 6 -1.<_>0 17 24 3 2.<_><_>5 2 12 8 -1.<_>5 2 6 4 2.<_>11 6 6 4 2.<_><_>8 9 9 6 -1.<_>11 9 3 6 3.<_><_>4 3 16 4 -1.<_>4 5 16 2 2.<_><_>10 2 4 10 -1.<_>10 7 4 5 2.<_><_>8 4 5 8 -1.<_>8 8 5 4 2.<_><_>11 5 9 12 -1.<_>11 9 9 4 3.<_><_>4 5 9 12 -1.<_>4 9 9 4 3.<_><_>14 6 6 9 -1.<_>14 9 6 3 3.<_><_>2 4 20 12 -1.<_>2 8 20 4 3.<_><_>4 4 17 16 -1.<_>4 12 17 8 2.<_><_>8 7 7 6 -1.<_>8 10 7 3 2.<_><_>1 9 23 2 -1.<_>1 10 23 1 2.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>13 3 4 9 -1.<_>13 3 2 9 2.<_><_>8 1 6 13 -1.<_>10 1 2 13 3.<_><_>4 22 18 2 -1.<_>4 23 18 1 2.<_><_>3 10 9 6 -1.<_>6 10 3 6 3.<_><_>14 0 2 24 -1.<_>14 0 1 24 2.<_><_>8 0 2 24 -1.<_>9 0 1 24 2.<_><_>3 2 18 10 -1.<_>9 2 6 10 3.<_><_>4 13 15 6 -1.<_>9 13 5 6 3.<_><_>3 21 18 3 -1.<_>9 21 6 3 3.<_><_>9 1 4 11 -1.<_>11 1 2 11 2.<_><_>9 7 10 4 -1.<_>9 7 5 4 2.<_><_>7 0 10 18 -1.<_>12 0 5 18 2.<_><_>12 1 6 16 -1.<_>14 1 2 16 3.<_><_>6 1 6 16 -1.<_>8 1 2 16 3.<_><_>18 2 6 6 -1.<_>18 5 6 3 2.<_><_>3 5 18 2 -1.<_>3 6 18 1 2.<_><_>18 2 6 6 -1.<_>18 5 6 3 2.<_><_>0 2 6 6 -1.<_>0 5 6 3 2.<_><_>13 11 11 6 -1.<_>13 13 11 2 3.<_><_>5 7 10 4 -1.<_>10 7 5 4 2.<_><_>11 9 10 7 -1.<_>11 9 5 7 2.<_><_>3 9 10 7 -1.<_>8 9 5 7 2.<_><_>16 4 6 6 -1.<_>16 4 3 6 2.<_><_>5 6 10 8 -1.<_>5 6 5 4 2.<_>10 10 5 4 2.<_><_>7 21 16 3 -1.<_>7 21 8 3 2.<_><_>1 21 16 3 -1.<_>9 21 8 3 2.<_><_>2 5 22 14 -1.<_>13 5 11 7 2.<_>2 12 11 7 2.<_><_>3 10 8 10 -1.<_>3 10 4 5 2.<_>7 15 4 5 2.<_><_>17 0 6 12 -1.<_>20 0 3 6 2.<_>17 6 3 6 2.<_><_>5 2 6 18 -1.<_>7 2 2 18 3.<_><_>13 0 6 9 -1.<_>15 0 2 9 3.<_><_>0 12 7 9 -1.<_>0 15 7 3 3.<_><_>15 13 8 10 -1.<_>19 13 4 5 2.<_>15 18 4 5 2.<_><_>1 0 6 12 -1.<_>1 0 3 6 2.<_>4 6 3 6 2.<_><_>12 1 3 12 -1.<_>12 7 3 6 2.<_><_>1 13 8 10 -1.<_>1 13 4 5 2.<_>5 18 4 5 2.<_><_>3 21 19 2 -1.<_>3 22 19 1 2.<_><_>6 3 4 13 -1.<_>8 3 2 13 2.<_><_>5 10 18 3 -1.<_>5 11 18 1 3.<_><_>9 3 5 12 -1.<_>9 7 5 4 3.<_><_>11 2 4 15 -1.<_>11 7 4 5 3.<_><_>4 1 16 4 -1.<_>4 3 16 2 2.<_><_>6 0 18 3 -1.<_>6 1 18 1 3.<_><_>5 1 10 8 -1.<_>5 1 5 4 2.<_>10 5 5 4 2.<_><_>11 18 12 6 -1.<_>17 18 6 3 2.<_>11 21 6 3 2.<_><_>5 15 12 3 -1.<_>11 15 6 3 2.<_><_>1 10 22 4 -1.<_>1 10 11 4 2.<_><_>7 9 9 6 -1.<_>10 9 3 6 3.<_><_>6 11 12 5 -1.<_>10 11 4 5 3.<_><_>6 7 10 7 -1.<_>11 7 5 7 2.<_><_>11 2 8 10 -1.<_>11 2 4 10 2.<_><_>5 2 8 10 -1.<_>9 2 4 10 2.<_><_>6 4 18 6 -1.<_>15 4 9 3 2.<_>6 7 9 3 2.<_><_>0 5 10 9 -1.<_>0 8 10 3 3.<_><_>2 7 21 6 -1.<_>2 9 21 2 3.<_><_>0 4 22 16 -1.<_>0 4 11 8 2.<_>11 12 11 8 2.<_><_>9 0 6 22 -1.<_>9 11 6 11 2.<_><_>9 1 3 12 -1.<_>9 7 3 6 2.<_><_>12 0 12 18 -1.<_>18 0 6 9 2.<_>12 9 6 9 2.<_><_>0 0 12 18 -1.<_>0 0 6 9 2.<_>6 9 6 9 2.<_><_>1 1 22 4 -1.<_>12 1 11 2 2.<_>1 3 11 2 2.<_><_>3 0 18 4 -1.<_>3 2 18 2 2.<_><_>2 5 22 6 -1.<_>2 7 22 2 3.<_><_>5 0 6 9 -1.<_>5 3 6 3 3.<_><_>10 14 6 9 -1.<_>12 14 2 9 3.<_><_>8 14 6 9 -1.<_>10 14 2 9 3.<_><_>5 18 18 3 -1.<_>5 19 18 1 3.<_><_>6 0 6 13 -1.<_>9 0 3 13 2.<_><_>7 4 12 4 -1.<_>7 4 6 4 2.<_><_>5 2 12 6 -1.<_>9 2 4 6 3.<_><_>4 1 18 3 -1.<_>4 2 18 1 3.<_><_>0 8 6 12 -1.<_>0 12 6 4 3.<_><_>9 15 6 9 -1.<_>11 15 2 9 3.<_><_>9 10 6 13 -1.<_>11 10 2 13 3.<_><_>6 17 18 2 -1.<_>6 18 18 1 2.<_><_>9 4 6 9 -1.<_>11 4 2 9 3.<_><_>10 0 6 9 -1.<_>12 0 2 9 3.<_><_>5 6 10 8 -1.<_>5 6 5 4 2.<_>10 10 5 4 2.<_><_>14 9 5 8 -1.<_>14 13 5 4 2.<_><_>5 9 5 8 -1.<_>5 13 5 4 2.<_><_>14 11 9 6 -1.<_>14 13 9 2 3.<_><_>0 2 23 15 -1.<_>0 7 23 5 3.<_><_>16 0 8 12 -1.<_>16 6 8 6 2.<_><_>4 15 6 9 -1.<_>4 18 6 3 3.<_><_>8 18 9 4 -1.<_>8 20 9 2 2.<_><_>0 17 18 3 -1.<_>0 18 18 1 3.<_><_>13 11 11 6 -1.<_>13 13 11 2 3.<_><_>0 11 11 6 -1.<_>0 13 11 2 3.<_><_>0 9 24 6 -1.<_>12 9 12 3 2.<_>0 12 12 3 2.<_><_>6 16 8 8 -1.<_>6 20 8 4 2.<_><_>10 16 14 6 -1.<_>10 18 14 2 3.<_><_>1 1 21 3 -1.<_>1 2 21 1 3.<_><_>0 2 24 3 -1.<_>0 2 12 3 2.<_><_>2 15 8 5 -1.<_>6 15 4 5 2.<_><_>2 11 21 3 -1.<_>9 11 7 3 3.<_><_>1 18 12 6 -1.<_>1 18 6 3 2.<_>7 21 6 3 2.<_><_>10 14 4 10 -1.<_>10 19 4 5 2.<_><_>7 7 4 10 -1.<_>7 12 4 5 2.<_><_>9 8 6 12 -1.<_>9 12 6 4 3.<_><_>7 1 9 6 -1.<_>10 1 3 6 3.<_><_>3 14 19 2 -1.<_>3 15 19 1 2.<_><_>7 7 10 10 -1.<_>7 7 5 5 2.<_>12 12 5 5 2.<_><_>3 12 18 12 -1.<_>3 12 9 12 2.<_><_>8 0 6 12 -1.<_>10 0 2 12 3.<_><_>3 0 17 9 -1.<_>3 3 17 3 3.<_><_>6 0 12 11 -1.<_>10 0 4 11 3.<_><_>1 0 6 13 -1.<_>4 0 3 13 2.<_><_>5 8 16 6 -1.<_>5 11 16 3 2.<_><_>8 8 5 12 -1.<_>8 14 5 6 2.<_><_>3 21 18 3 -1.<_>9 21 6 3 3.<_><_>0 0 6 6 -1.<_>3 0 3 6 2.<_><_>2 0 20 3 -1.<_>2 1 20 1 3.<_><_>4 6 15 10 -1.<_>9 6 5 10 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>9 0 6 9 -1.<_>11 0 2 9 3.<_><_>14 0 6 9 -1.<_>16 0 2 9 3.<_><_>7 16 9 6 -1.<_>7 18 9 2 3.<_><_>14 0 6 9 -1.<_>16 0 2 9 3.<_><_>4 0 6 9 -1.<_>6 0 2 9 3.<_><_>17 1 6 16 -1.<_>19 1 2 16 3.<_><_>1 1 6 16 -1.<_>3 1 2 16 3.<_><_>14 13 6 9 -1.<_>14 16 6 3 3.<_><_>0 0 6 9 -1.<_>0 3 6 3 3.<_><_>9 5 6 6 -1.<_>9 5 3 6 2.<_><_>3 10 9 6 -1.<_>6 10 3 6 3.<_><_>14 7 3 16 -1.<_>14 15 3 8 2.<_><_>4 10 14 12 -1.<_>4 10 7 6 2.<_>11 16 7 6 2.<_><_>7 6 12 6 -1.<_>7 8 12 2 3.<_><_>7 2 4 20 -1.<_>9 2 2 20 2.<_><_>14 13 6 9 -1.<_>14 16 6 3 3.<_><_>10 6 4 9 -1.<_>12 6 2 9 2.<_><_>14 13 6 9 -1.<_>14 16 6 3 3.<_><_>5 20 14 4 -1.<_>5 22 14 2 2.<_><_>4 4 16 12 -1.<_>4 10 16 6 2.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>3 0 21 4 -1.<_>3 2 21 2 2.<_><_>4 13 6 9 -1.<_>4 16 6 3 3.<_><_>16 16 5 8 -1.<_>16 20 5 4 2.<_><_>4 0 16 16 -1.<_>4 0 8 8 2.<_>12 8 8 8 2.<_><_>6 6 14 6 -1.<_>13 6 7 3 2.<_>6 9 7 3 2.<_><_>10 5 4 15 -1.<_>10 10 4 5 3.<_><_>9 15 12 8 -1.<_>15 15 6 4 2.<_>9 19 6 4 2.<_><_>6 7 12 4 -1.<_>12 7 6 4 2.<_><_>5 6 14 6 -1.<_>12 6 7 3 2.<_>5 9 7 3 2.<_><_>3 6 18 10 -1.<_>3 6 9 5 2.<_>12 11 9 5 2.<_><_>6 0 18 21 -1.<_>12 0 6 21 3.<_><_>0 0 24 21 -1.<_>8 0 8 21 3.<_><_>6 18 18 3 -1.<_>6 19 18 1 3.<_><_>0 15 9 6 -1.<_>0 17 9 2 3.<_><_>4 3 19 2 -1.<_>4 4 19 1 2.<_><_>0 3 24 2 -1.<_>0 4 24 1 2.<_><_>15 14 9 4 -1.<_>15 16 9 2 2.<_><_>0 14 9 4 -1.<_>0 16 9 2 2.<_><_>6 15 18 2 -1.<_>6 16 18 1 2.<_><_>3 17 18 3 -1.<_>3 18 18 1 3.<_><_>12 0 3 23 -1.<_>13 0 1 23 3.<_><_>6 0 8 6 -1.<_>6 3 8 3 2.<_><_>6 16 18 3 -1.<_>6 17 18 1 3.<_><_>9 0 3 23 -1.<_>10 0 1 23 3.<_><_>10 7 4 10 -1.<_>10 12 4 5 2.<_><_>7 8 10 12 -1.<_>7 12 10 4 3.<_><_>14 9 6 14 -1.<_>17 9 3 7 2.<_>14 16 3 7 2.<_><_>2 0 10 9 -1.<_>2 3 10 3 3.<_><_>11 1 5 12 -1.<_>11 7 5 6 2.<_><_>1 4 12 10 -1.<_>1 4 6 5 2.<_>7 9 6 5 2.<_><_>15 1 9 4 -1.<_>15 3 9 2 2.<_><_>1 2 8 10 -1.<_>1 2 4 5 2.<_>5 7 4 5 2.<_><_>10 1 5 12 -1.<_>10 5 5 4 3.<_><_>4 0 14 24 -1.<_>11 0 7 24 2.<_><_>7 17 10 4 -1.<_>7 19 10 2 2.<_><_>10 14 4 10 -1.<_>10 19 4 5 2.<_><_>13 15 6 9 -1.<_>15 15 2 9 3.<_><_>3 21 18 3 -1.<_>3 22 18 1 3.<_><_>13 15 6 9 -1.<_>15 15 2 9 3.<_><_>5 15 6 9 -1.<_>7 15 2 9 3.<_><_>10 6 4 18 -1.<_>12 6 2 9 2.<_>10 15 2 9 2.<_><_>7 3 6 11 -1.<_>9 3 2 11 3.<_><_>15 1 9 4 -1.<_>15 3 9 2 2.<_><_>5 4 14 8 -1.<_>5 8 14 4 2.<_><_>8 1 15 9 -1.<_>8 4 15 3 3.<_><_>7 2 8 10 -1.<_>7 2 4 5 2.<_>11 7 4 5 2.<_><_>12 2 6 12 -1.<_>12 2 3 12 2.<_><_>6 2 6 12 -1.<_>9 2 3 12 2.<_><_>7 7 12 4 -1.<_>7 7 6 4 2.<_><_>6 3 12 10 -1.<_>10 3 4 10 3.<_><_>5 6 16 6 -1.<_>13 6 8 3 2.<_>5 9 8 3 2.<_><_>3 1 18 9 -1.<_>9 1 6 9 3.<_><_>3 8 18 5 -1.<_>9 8 6 5 3.<_><_>0 0 24 22 -1.<_>0 0 12 11 2.<_>12 11 12 11 2.<_><_>14 16 9 6 -1.<_>14 18 9 2 3.<_><_>0 16 24 8 -1.<_>0 20 24 4 2.<_><_>1 19 22 4 -1.<_>12 19 11 2 2.<_>1 21 11 2 2.<_><_>1 16 9 6 -1.<_>1 18 9 2 3.<_><_>7 8 10 4 -1.<_>7 8 5 4 2.<_><_>9 15 6 9 -1.<_>11 15 2 9 3.<_><_>10 18 12 6 -1.<_>16 18 6 3 2.<_>10 21 6 3 2.<_><_>2 18 12 6 -1.<_>2 18 6 3 2.<_>8 21 6 3 2.<_><_>8 3 16 9 -1.<_>8 6 16 3 3.<_><_>0 5 10 6 -1.<_>0 7 10 2 3.<_><_>5 5 18 3 -1.<_>5 6 18 1 3.<_><_>2 6 9 6 -1.<_>2 9 9 3 2.<_><_>14 2 10 9 -1.<_>14 5 10 3 3.<_><_>3 6 18 3 -1.<_>3 7 18 1 3.<_><_>9 2 15 6 -1.<_>9 4 15 2 3.<_><_>4 8 15 6 -1.<_>4 10 15 2 3.<_><_>0 5 24 4 -1.<_>12 5 12 2 2.<_>0 7 12 2 2.<_><_>7 8 6 12 -1.<_>9 8 2 12 3.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>0 12 6 12 -1.<_>0 12 3 6 2.<_>3 18 3 6 2.<_><_>14 12 10 6 -1.<_>14 14 10 2 3.<_><_>2 7 18 9 -1.<_>2 10 18 3 3.<_><_>11 14 10 9 -1.<_>11 17 10 3 3.<_><_>7 6 10 8 -1.<_>7 6 5 4 2.<_>12 10 5 4 2.<_><_>6 6 14 6 -1.<_>13 6 7 3 2.<_>6 9 7 3 2.<_><_>4 13 9 7 -1.<_>7 13 3 7 3.<_><_>14 10 6 12 -1.<_>17 10 3 6 2.<_>14 16 3 6 2.<_><_>4 10 6 12 -1.<_>4 10 3 6 2.<_>7 16 3 6 2.<_><_>13 9 8 6 -1.<_>13 9 4 6 2.<_><_>8 3 4 14 -1.<_>10 3 2 14 2.<_><_>17 0 3 18 -1.<_>18 0 1 18 3.<_><_>4 12 16 12 -1.<_>12 12 8 12 2.<_><_>15 0 6 14 -1.<_>17 0 2 14 3.<_><_>3 0 6 14 -1.<_>5 0 2 14 3.<_><_>12 2 12 20 -1.<_>16 2 4 20 3.<_><_>0 2 12 20 -1.<_>4 2 4 20 3.<_><_>16 0 6 17 -1.<_>18 0 2 17 3.<_><_>2 0 6 17 -1.<_>4 0 2 17 3.<_><_>15 6 9 6 -1.<_>15 8 9 2 3.<_><_>0 6 9 6 -1.<_>0 8 9 2 3.<_><_>18 1 6 13 -1.<_>20 1 2 13 3.<_><_>0 1 6 13 -1.<_>2 1 2 13 3.<_><_>16 0 4 9 -1.<_>16 0 2 9 2.<_><_>5 10 12 7 -1.<_>9 10 4 7 3.<_><_>12 9 12 6 -1.<_>12 11 12 2 3.<_><_>0 9 12 6 -1.<_>0 11 12 2 3.<_><_>5 7 14 9 -1.<_>5 10 14 3 3.<_><_>0 15 20 3 -1.<_>0 16 20 1 3.<_><_>8 10 8 10 -1.<_>12 10 4 5 2.<_>8 15 4 5 2.<_><_>5 4 13 9 -1.<_>5 7 13 3 3.<_><_>10 2 6 18 -1.<_>10 8 6 6 3.<_><_>6 0 6 9 -1.<_>8 0 2 9 3.<_><_>6 9 12 4 -1.<_>6 11 12 2 2.<_><_>3 2 15 12 -1.<_>3 6 15 4 3.<_><_>12 0 12 5 -1.<_>16 0 4 5 3.<_><_>0 15 18 3 -1.<_>6 15 6 3 3.<_><_>0 14 24 5 -1.<_>8 14 8 5 3.<_><_>5 1 3 18 -1.<_>6 1 1 18 3.<_><_>10 0 4 14 -1.<_>10 0 2 14 2.<_><_>9 3 4 9 -1.<_>11 3 2 9 2.<_><_>8 2 12 6 -1.<_>14 2 6 3 2.<_>8 5 6 3 2.<_><_>0 4 17 4 -1.<_>0 6 17 2 2.<_><_>16 16 5 8 -1.<_>16 20 5 4 2.<_><_>3 16 5 8 -1.<_>3 20 5 4 2.<_><_>6 18 18 2 -1.<_>6 19 18 1 2.<_><_>0 0 12 5 -1.<_>4 0 4 5 3.<_><_>14 3 6 12 -1.<_>17 3 3 6 2.<_>14 9 3 6 2.<_><_>0 12 6 12 -1.<_>2 12 2 12 3.<_><_>2 3 21 3 -1.<_>2 4 21 1 3.<_><_>4 3 6 12 -1.<_>4 3 3 6 2.<_>7 9 3 6 2.<_><_>12 8 12 6 -1.<_>18 8 6 3 2.<_>12 11 6 3 2.<_><_>0 15 16 9 -1.<_>8 15 8 9 2.<_><_>6 13 18 5 -1.<_>6 13 9 5 2.<_><_>1 6 15 6 -1.<_>6 6 5 6 3.<_><_>11 9 9 6 -1.<_>14 9 3 6 3.<_><_>3 0 15 11 -1.<_>8 0 5 11 3.<_><_>15 3 3 18 -1.<_>15 9 3 6 3.<_><_>6 3 3 18 -1.<_>6 9 3 6 3.<_><_>9 5 10 8 -1.<_>14 5 5 4 2.<_>9 9 5 4 2.<_><_>4 4 16 8 -1.<_>4 4 8 4 2.<_>12 8 8 4 2.<_><_>7 7 12 3 -1.<_>7 7 6 3 2.<_><_>5 0 9 13 -1.<_>8 0 3 13 3.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>8 1 10 9 -1.<_>8 4 10 3 3.<_><_>0 2 18 2 -1.<_>0 3 18 1 2.<_><_>10 13 14 6 -1.<_>17 13 7 3 2.<_>10 16 7 3 2.<_><_>0 13 14 6 -1.<_>0 13 7 3 2.<_>7 16 7 3 2.<_><_>20 2 3 21 -1.<_>21 2 1 21 3.<_><_>0 9 5 12 -1.<_>0 13 5 4 3.<_><_>12 6 12 6 -1.<_>12 8 12 2 3.<_><_>1 8 20 3 -1.<_>1 9 20 1 3.<_><_>5 7 19 3 -1.<_>5 8 19 1 3.<_><_>1 12 9 6 -1.<_>1 14 9 2 3.<_><_>6 10 14 12 -1.<_>6 14 14 4 3.<_><_>5 6 14 18 -1.<_>5 12 14 6 3.<_><_>11 12 9 7 -1.<_>14 12 3 7 3.<_><_>1 15 18 4 -1.<_>1 17 18 2 2.<_><_>11 14 6 9 -1.<_>11 17 6 3 3.<_><_>0 8 18 4 -1.<_>0 8 9 2 2.<_>9 10 9 2 2.<_><_>3 10 20 6 -1.<_>13 10 10 3 2.<_>3 13 10 3 2.<_><_>1 10 20 6 -1.<_>1 10 10 3 2.<_>11 13 10 3 2.<_><_>0 9 24 2 -1.<_>0 9 12 2 2.<_><_>1 12 20 8 -1.<_>1 12 10 4 2.<_>11 16 10 4 2.<_><_>11 12 9 7 -1.<_>14 12 3 7 3.<_><_>4 12 9 7 -1.<_>7 12 3 7 3.<_><_>12 12 8 5 -1.<_>12 12 4 5 2.<_><_>4 12 8 5 -1.<_>8 12 4 5 2.<_><_>13 10 4 10 -1.<_>13 10 2 10 2.<_><_>1 15 20 2 -1.<_>11 15 10 2 2.<_><_>9 10 6 6 -1.<_>9 10 3 6 2.<_><_>0 1 21 3 -1.<_>7 1 7 3 3.<_><_>6 4 13 9 -1.<_>6 7 13 3 3.<_><_>6 5 12 5 -1.<_>10 5 4 5 3.<_><_>10 10 10 6 -1.<_>10 12 10 2 3.<_><_>6 12 5 8 -1.<_>6 16 5 4 2.<_><_>13 0 6 9 -1.<_>15 0 2 9 3.<_><_>2 10 18 6 -1.<_>8 10 6 6 3.<_><_>11 2 9 4 -1.<_>11 4 9 2 2.<_><_>1 20 21 3 -1.<_>8 20 7 3 3.<_><_>1 10 22 2 -1.<_>1 11 22 1 2.<_><_>0 17 18 3 -1.<_>0 18 18 1 3.<_><_>13 0 6 9 -1.<_>15 0 2 9 3.<_><_>5 0 6 9 -1.<_>7 0 2 9 3.<_><_>18 2 6 20 -1.<_>20 2 2 20 3.<_><_>0 2 6 20 -1.<_>2 2 2 20 3.<_><_>11 7 6 14 -1.<_>14 7 3 7 2.<_>11 14 3 7 2.<_><_>0 1 4 9 -1.<_>2 1 2 9 2.<_><_>12 14 9 4 -1.<_>12 16 9 2 2.<_><_>1 13 9 4 -1.<_>1 15 9 2 2.<_><_>7 6 15 6 -1.<_>7 8 15 2 3.<_><_>8 2 3 18 -1.<_>8 8 3 6 3.<_><_>6 6 12 6 -1.<_>12 6 6 3 2.<_>6 9 6 3 2.<_><_>2 19 20 4 -1.<_>2 19 10 2 2.<_>12 21 10 2 2.<_><_>14 15 6 9 -1.<_>14 18 6 3 3.<_><_>3 5 18 14 -1.<_>3 5 9 7 2.<_>12 12 9 7 2.<_><_>15 6 4 18 -1.<_>17 6 2 9 2.<_>15 15 2 9 2.<_><_>5 6 4 18 -1.<_>5 6 2 9 2.<_>7 15 2 9 2.<_><_>11 0 6 9 -1.<_>13 0 2 9 3.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>11 5 6 9 -1.<_>13 5 2 9 3.<_><_>9 5 6 6 -1.<_>12 5 3 6 2.<_><_>4 1 16 6 -1.<_>12 1 8 3 2.<_>4 4 8 3 2.<_><_>9 13 6 11 -1.<_>11 13 2 11 3.<_><_>17 1 6 12 -1.<_>20 1 3 6 2.<_>17 7 3 6 2.<_><_>1 17 18 3 -1.<_>1 18 18 1 3.<_><_>7 13 10 8 -1.<_>7 17 10 4 2.<_><_>6 18 10 6 -1.<_>6 20 10 2 3.<_><_>9 14 9 4 -1.<_>9 16 9 2 2.<_><_>1 1 6 12 -1.<_>1 1 3 6 2.<_>4 7 3 6 2.<_><_>19 4 5 12 -1.<_>19 8 5 4 3.<_><_>0 0 8 8 -1.<_>4 0 4 8 2.<_><_>3 5 19 3 -1.<_>3 6 19 1 3.<_><_>1 5 12 6 -1.<_>1 5 6 3 2.<_>7 8 6 3 2.<_><_>2 1 21 8 -1.<_>9 1 7 8 3.<_><_>4 1 16 8 -1.<_>4 5 16 4 2.<_><_>6 0 18 3 -1.<_>6 1 18 1 3.<_><_>4 4 10 14 -1.<_>4 11 10 7 2.<_><_>15 6 4 10 -1.<_>15 11 4 5 2.<_><_>3 18 18 3 -1.<_>9 18 6 3 3.<_><_>8 18 12 6 -1.<_>12 18 4 6 3.<_><_>3 15 6 9 -1.<_>6 15 3 9 2.<_><_>15 7 6 8 -1.<_>15 11 6 4 2.<_><_>3 7 6 8 -1.<_>3 11 6 4 2.<_><_>5 9 18 6 -1.<_>14 9 9 3 2.<_>5 12 9 3 2.<_><_>1 13 12 6 -1.<_>1 15 12 2 3.<_><_>14 15 10 6 -1.<_>14 17 10 2 3.<_><_>0 15 10 6 -1.<_>0 17 10 2 3.<_><_>15 13 6 9 -1.<_>15 16 6 3 3.<_><_>3 13 6 9 -1.<_>3 16 6 3 3.<_><_>9 5 8 8 -1.<_>9 5 4 8 2.<_><_>1 18 12 6 -1.<_>1 18 6 3 2.<_>7 21 6 3 2.<_><_>13 19 10 4 -1.<_>13 21 10 2 2.<_><_>1 19 10 4 -1.<_>1 21 10 2 2.<_><_>6 19 18 3 -1.<_>6 20 18 1 3.<_><_>8 14 4 10 -1.<_>8 19 4 5 2.<_><_>0 0 24 6 -1.<_>0 2 24 2 3.<_><_>0 1 6 9 -1.<_>0 4 6 3 3.<_><_>4 9 20 6 -1.<_>14 9 10 3 2.<_>4 12 10 3 2.<_><_>1 15 19 8 -1.<_>1 19 19 4 2.<_><_>14 0 10 6 -1.<_>14 2 10 2 3.<_><_>1 10 21 14 -1.<_>8 10 7 14 3.<_><_>10 10 8 8 -1.<_>10 10 4 8 2.<_><_>6 8 10 4 -1.<_>11 8 5 4 2.<_><_>10 5 4 9 -1.<_>10 5 2 9 2.<_><_>7 5 6 10 -1.<_>9 5 2 10 3.<_><_>14 4 4 13 -1.<_>14 4 2 13 2.<_><_>6 4 4 13 -1.<_>8 4 2 13 2.<_><_>8 7 9 6 -1.<_>11 7 3 6 3.<_><_>3 6 16 6 -1.<_>3 6 8 3 2.<_>11 9 8 3 2.<_><_>5 4 16 14 -1.<_>13 4 8 7 2.<_>5 11 8 7 2.<_><_>0 0 24 4 -1.<_>0 0 12 2 2.<_>12 2 12 2 2.<_><_>9 1 9 6 -1.<_>12 1 3 6 3.<_><_>4 1 14 4 -1.<_>11 1 7 4 2.<_><_>10 14 7 9 -1.<_>10 17 7 3 3.<_><_>8 3 8 10 -1.<_>8 3 4 5 2.<_>12 8 4 5 2.<_><_>7 3 12 5 -1.<_>11 3 4 5 3.<_><_>8 2 4 13 -1.<_>10 2 2 13 2.<_><_>11 2 3 19 -1.<_>12 2 1 19 3.<_><_>7 7 9 6 -1.<_>10 7 3 6 3.<_><_>4 22 20 2 -1.<_>4 22 10 2 2.<_><_>0 16 24 4 -1.<_>0 16 12 2 2.<_>12 18 12 2 2.<_><_>7 3 12 5 -1.<_>11 3 4 5 3.<_><_>1 10 8 14 -1.<_>1 10 4 7 2.<_>5 17 4 7 2.<_><_>11 16 6 6 -1.<_>11 19 6 3 2.<_><_>6 0 10 24 -1.<_>6 0 5 12 2.<_>11 12 5 12 2.<_><_>7 5 14 14 -1.<_>14 5 7 7 2.<_>7 12 7 7 2.<_><_>7 8 10 8 -1.<_>7 8 5 4 2.<_>12 12 5 4 2.<_><_>9 1 9 6 -1.<_>12 1 3 6 3.<_><_>0 6 24 3 -1.<_>12 6 12 3 2.<_><_>7 3 12 5 -1.<_>11 3 4 5 3.<_><_>1 13 22 4 -1.<_>1 13 11 2 2.<_>12 15 11 2 2.<_><_>9 12 12 6 -1.<_>9 14 12 2 3.<_><_>0 5 9 6 -1.<_>0 7 9 2 3.<_><_>1 5 23 6 -1.<_>1 7 23 2 3.<_><_>1 6 19 12 -1.<_>1 10 19 4 3.<_><_>9 1 6 21 -1.<_>9 8 6 7 3.<_><_>3 19 18 3 -1.<_>9 19 6 3 3.<_><_>9 14 6 9 -1.<_>11 14 2 9 3.<_><_>9 6 4 12 -1.<_>11 6 2 12 2.<_><_>16 0 6 9 -1.<_>18 0 2 9 3.<_><_>2 0 6 9 -1.<_>4 0 2 9 3.<_><_>13 1 4 22 -1.<_>15 1 2 11 2.<_>13 12 2 11 2.<_><_>1 8 8 12 -1.<_>1 14 8 6 2.<_><_>14 7 7 9 -1.<_>14 10 7 3 3.<_><_>3 12 18 4 -1.<_>3 12 9 2 2.<_>12 14 9 2 2.<_><_>13 1 4 22 -1.<_>15 1 2 11 2.<_>13 12 2 11 2.<_><_>7 1 4 22 -1.<_>7 1 2 11 2.<_>9 12 2 11 2.<_><_>4 7 20 4 -1.<_>14 7 10 2 2.<_>4 9 10 2 2.<_><_>9 10 6 7 -1.<_>12 10 3 7 2.<_><_>7 7 10 4 -1.<_>7 7 5 4 2.<_><_>0 3 4 15 -1.<_>0 8 4 5 3.<_><_>15 0 8 12 -1.<_>19 0 4 6 2.<_>15 6 4 6 2.<_><_>1 0 8 12 -1.<_>1 0 4 6 2.<_>5 6 4 6 2.<_><_>14 5 6 16 -1.<_>16 5 2 16 3.<_><_>4 5 6 16 -1.<_>6 5 2 16 3.<_><_>15 0 6 16 -1.<_>17 0 2 16 3.<_><_>3 0 6 16 -1.<_>5 0 2 16 3.<_><_>0 2 24 3 -1.<_>0 3 24 1 3.<_><_>7 1 10 4 -1.<_>7 3 10 2 2.<_><_>1 0 23 8 -1.<_>1 4 23 4 2.<_><_>1 17 19 3 -1.<_>1 18 19 1 3.<_><_>6 18 18 2 -1.<_>6 19 18 1 2.<_><_>1 17 9 6 -1.<_>1 19 9 2 3.<_><_>15 15 6 9 -1.<_>15 18 6 3 3.<_><_>3 15 6 9 -1.<_>3 18 6 3 3.<_><_>4 14 20 6 -1.<_>4 17 20 3 2.<_><_>0 10 6 14 -1.<_>0 10 3 7 2.<_>3 17 3 7 2.<_><_>6 18 18 3 -1.<_>6 19 18 1 3.<_><_>4 12 9 7 -1.<_>7 12 3 7 3.<_><_>6 10 18 5 -1.<_>12 10 6 5 3.<_><_>0 10 18 5 -1.<_>6 10 6 5 3.<_><_>3 2 18 9 -1.<_>9 2 6 9 3.<_><_>4 6 10 10 -1.<_>4 6 5 5 2.<_>9 11 5 5 2.<_><_>20 14 4 9 -1.<_>20 14 2 9 2.<_><_>0 14 4 9 -1.<_>2 14 2 9 2.<_><_>11 1 4 20 -1.<_>13 1 2 10 2.<_>11 11 2 10 2.<_><_>6 21 12 3 -1.<_>12 21 6 3 2.<_><_>11 1 4 20 -1.<_>13 1 2 10 2.<_>11 11 2 10 2.<_><_>1 16 10 8 -1.<_>1 16 5 4 2.<_>6 20 5 4 2.<_><_>11 1 4 20 -1.<_>13 1 2 10 2.<_>11 11 2 10 2.<_><_>1 0 3 19 -1.<_>2 0 1 19 3.<_><_>11 1 4 20 -1.<_>13 1 2 10 2.<_>11 11 2 10 2.<_><_>0 1 6 9 -1.<_>2 1 2 9 3.<_><_>3 7 19 4 -1.<_>3 9 19 2 2.<_><_>7 14 9 6 -1.<_>7 16 9 2 3.<_><_>17 1 7 6 -1.<_>17 4 7 3 2.<_><_>5 0 14 8 -1.<_>5 4 14 4 2.<_><_>16 1 8 6 -1.<_>16 4 8 3 2.<_><_>0 1 8 6 -1.<_>0 4 8 3 2.<_><_>6 0 18 4 -1.<_>15 0 9 2 2.<_>6 2 9 2 2.<_><_>0 14 9 6 -1.<_>0 16 9 2 3.<_><_>3 7 18 8 -1.<_>9 7 6 8 3.<_><_>2 11 6 9 -1.<_>4 11 2 9 3.<_><_>10 5 6 9 -1.<_>12 5 2 9 3.<_><_>10 6 4 18 -1.<_>10 6 2 9 2.<_>12 15 2 9 2.<_><_>11 1 4 20 -1.<_>13 1 2 10 2.<_>11 11 2 10 2.<_><_>9 1 4 20 -1.<_>9 1 2 10 2.<_>11 11 2 10 2.<_><_>5 9 18 6 -1.<_>14 9 9 3 2.<_>5 12 9 3 2.<_><_>6 4 6 9 -1.<_>8 4 2 9 3.<_><_>10 16 8 6 -1.<_>10 16 4 6 2.<_><_>0 0 18 8 -1.<_>0 0 9 4 2.<_>9 4 9 4 2.<_><_>6 5 14 12 -1.<_>13 5 7 6 2.<_>6 11 7 6 2.<_><_>4 3 15 7 -1.<_>9 3 5 7 3.<_><_>14 12 10 6 -1.<_>14 14 10 2 3.<_><_>0 11 4 10 -1.<_>0 16 4 5 2.<_><_>1 10 22 3 -1.<_>1 11 22 1 3.<_><_>8 9 6 10 -1.<_>10 9 2 10 3.<_><_>13 2 6 12 -1.<_>16 2 3 6 2.<_>13 8 3 6 2.<_><_>10 6 4 18 -1.<_>10 6 2 9 2.<_>12 15 2 9 2.<_><_>7 8 10 16 -1.<_>12 8 5 8 2.<_>7 16 5 8 2.<_><_>8 1 8 12 -1.<_>8 1 4 6 2.<_>12 7 4 6 2.<_><_>7 1 12 14 -1.<_>13 1 6 7 2.<_>7 8 6 7 2.<_><_>2 14 12 6 -1.<_>2 16 12 2 3.<_><_>11 16 6 6 -1.<_>11 19 6 3 2.<_><_>7 16 6 6 -1.<_>7 19 6 3 2.<_><_>13 4 4 10 -1.<_>13 4 2 10 2.<_><_>0 19 19 3 -1.<_>0 20 19 1 3.<_><_>12 8 6 8 -1.<_>12 12 6 4 2.<_><_>8 1 8 22 -1.<_>8 12 8 11 2.<_><_>12 8 6 8 -1.<_>12 12 6 4 2.<_><_>6 8 6 8 -1.<_>6 12 6 4 2.<_><_>14 5 6 9 -1.<_>14 8 6 3 3.<_><_>0 6 24 4 -1.<_>0 8 24 2 2.<_><_>14 12 10 6 -1.<_>14 14 10 2 3.<_><_>0 12 10 6 -1.<_>0 14 10 2 3.<_><_>4 6 19 3 -1.<_>4 7 19 1 3.<_><_>1 6 19 3 -1.<_>1 7 19 1 3.<_><_>4 0 16 9 -1.<_>4 3 16 3 3.<_><_>0 1 24 5 -1.<_>8 1 8 5 3.<_><_>3 6 6 15 -1.<_>3 11 6 5 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>0 17 18 3 -1.<_>0 18 18 1 3.<_><_>6 22 18 2 -1.<_>6 23 18 1 2.<_><_>2 12 6 9 -1.<_>2 15 6 3 3.<_><_>18 12 6 9 -1.<_>18 15 6 3 3.<_><_>0 12 6 9 -1.<_>0 15 6 3 3.<_><_>11 14 4 10 -1.<_>11 19 4 5 2.<_><_>9 6 6 16 -1.<_>9 14 6 8 2.<_><_>7 7 10 10 -1.<_>7 12 10 5 2.<_><_>1 3 6 13 -1.<_>3 3 2 13 3.<_><_>18 1 6 13 -1.<_>18 1 3 13 2.<_><_>5 1 6 9 -1.<_>7 1 2 9 3.<_><_>18 2 6 11 -1.<_>18 2 3 11 2.<_><_>0 2 6 11 -1.<_>3 2 3 11 2.<_><_>9 12 15 6 -1.<_>9 14 15 2 3.<_><_>2 2 20 3 -1.<_>2 3 20 1 3.<_><_>10 6 4 9 -1.<_>10 6 2 9 2.<_><_>5 6 12 14 -1.<_>5 6 6 7 2.<_>11 13 6 7 2.<_><_>9 0 6 9 -1.<_>11 0 2 9 3.<_><_>7 0 9 6 -1.<_>10 0 3 6 3.<_><_>10 6 6 9 -1.<_>12 6 2 9 3.<_><_>4 1 12 20 -1.<_>4 1 6 10 2.<_>10 11 6 10 2.<_><_>6 7 18 3 -1.<_>6 7 9 3 2.<_><_>0 7 18 3 -1.<_>9 7 9 3 2.<_><_>3 20 18 3 -1.<_>9 20 6 3 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>6 2 12 15 -1.<_>10 2 4 15 3.<_><_>2 3 18 3 -1.<_>2 4 18 1 3.<_><_>19 4 4 18 -1.<_>21 4 2 9 2.<_>19 13 2 9 2.<_><_>0 1 19 3 -1.<_>0 2 19 1 3.<_><_>5 0 15 4 -1.<_>5 2 15 2 2.<_><_>5 2 14 5 -1.<_>12 2 7 5 2.<_><_>1 2 22 14 -1.<_>1 2 11 14 2.<_><_>8 15 6 9 -1.<_>10 15 2 9 3.<_><_>6 17 18 3 -1.<_>6 18 18 1 3.<_><_>9 6 3 18 -1.<_>9 12 3 6 3.<_><_>2 0 20 3 -1.<_>2 1 20 1 3.<_><_>5 4 5 12 -1.<_>5 8 5 4 3.<_><_>8 6 12 5 -1.<_>12 6 4 5 3.<_><_>9 12 6 12 -1.<_>9 12 3 6 2.<_>12 18 3 6 2.<_><_>14 14 8 10 -1.<_>18 14 4 5 2.<_>14 19 4 5 2.<_><_>2 14 8 10 -1.<_>2 14 4 5 2.<_>6 19 4 5 2.<_><_>10 18 12 6 -1.<_>16 18 6 3 2.<_>10 21 6 3 2.<_><_>1 3 6 9 -1.<_>1 6 6 3 3.<_><_>11 3 3 20 -1.<_>12 3 1 20 3.<_><_>4 6 14 6 -1.<_>4 6 7 3 2.<_>11 9 7 3 2.<_><_>6 5 12 13 -1.<_>10 5 4 13 3.<_><_>5 4 4 15 -1.<_>5 9 4 5 3.<_><_>9 16 15 4 -1.<_>14 16 5 4 3.<_><_>7 8 6 14 -1.<_>7 8 3 7 2.<_>10 15 3 7 2.<_><_>7 6 10 6 -1.<_>7 8 10 2 3.<_><_>2 5 18 3 -1.<_>2 6 18 1 3.<_><_>5 1 15 8 -1.<_>5 5 15 4 2.<_><_>7 1 8 18 -1.<_>7 10 8 9 2.<_><_>0 10 24 3 -1.<_>0 11 24 1 3.<_><_>0 2 6 13 -1.<_>2 2 2 13 3.<_><_>16 0 8 10 -1.<_>20 0 4 5 2.<_>16 5 4 5 2.<_><_>5 1 10 9 -1.<_>5 4 10 3 3.<_><_>5 6 18 3 -1.<_>5 7 18 1 3.<_><_>0 1 24 3 -1.<_>0 2 24 1 3.<_><_>11 4 6 11 -1.<_>13 4 2 11 3.<_><_>0 0 8 10 -1.<_>0 0 4 5 2.<_>4 5 4 5 2.<_><_>4 16 18 3 -1.<_>4 17 18 1 3.<_><_>2 16 18 3 -1.<_>2 17 18 1 3.<_><_>3 0 18 10 -1.<_>12 0 9 5 2.<_>3 5 9 5 2.<_><_>2 3 20 21 -1.<_>12 3 10 21 2.<_><_>6 7 14 3 -1.<_>6 7 7 3 2.<_><_>0 9 12 6 -1.<_>0 9 6 3 2.<_>6 12 6 3 2.<_><_>3 14 21 4 -1.<_>10 14 7 4 3.<_><_>0 14 21 4 -1.<_>7 14 7 4 3.<_><_>5 21 18 3 -1.<_>11 21 6 3 3.<_><_>1 21 18 3 -1.<_>7 21 6 3 3.<_><_>19 4 4 18 -1.<_>21 4 2 9 2.<_>19 13 2 9 2.<_><_>3 7 18 3 -1.<_>3 8 18 1 3.<_><_>19 4 4 18 -1.<_>21 4 2 9 2.<_>19 13 2 9 2.<_><_>7 15 10 6 -1.<_>7 17 10 2 3.<_><_>9 13 11 9 -1.<_>9 16 11 3 3.<_><_>0 6 4 10 -1.<_>0 11 4 5 2.<_><_>15 16 9 6 -1.<_>15 18 9 2 3.<_><_>1 5 4 18 -1.<_>1 5 2 9 2.<_>3 14 2 9 2.<_><_>9 8 8 10 -1.<_>13 8 4 5 2.<_>9 13 4 5 2.<_><_>7 8 8 10 -1.<_>7 8 4 5 2.<_>11 13 4 5 2.<_><_>9 8 12 5 -1.<_>13 8 4 5 3.<_><_>7 8 9 7 -1.<_>10 8 3 7 3.<_><_>9 8 12 5 -1.<_>13 8 4 5 3.<_><_>7 6 9 7 -1.<_>10 6 3 7 3.<_><_>9 8 12 5 -1.<_>13 8 4 5 3.<_><_>10 5 4 18 -1.<_>10 11 4 6 3.<_><_>5 5 14 12 -1.<_>5 11 14 6 2.<_><_>0 1 11 4 -1.<_>0 3 11 2 2.<_><_>9 10 6 10 -1.<_>11 10 2 10 3.<_><_>2 17 11 6 -1.<_>2 19 11 2 3.<_><_>15 16 9 6 -1.<_>15 18 9 2 3.<_><_>1 10 18 2 -1.<_>1 11 18 1 2.<_><_>6 4 12 13 -1.<_>10 4 4 13 3.<_><_>0 18 18 3 -1.<_>0 19 18 1 3.<_><_>6 18 18 3 -1.<_>6 19 18 1 3.<_><_>0 16 9 6 -1.<_>0 18 9 2 3.<_><_>13 15 9 6 -1.<_>13 17 9 2 3.<_><_>2 15 9 6 -1.<_>2 17 9 2 3.<_><_>13 1 6 16 -1.<_>13 1 3 16 2.<_><_>5 1 6 16 -1.<_>8 1 3 16 2.<_><_>11 5 6 10 -1.<_>13 5 2 10 3.<_><_>7 5 6 10 -1.<_>9 5 2 10 3.<_><_>10 0 6 24 -1.<_>12 0 2 24 3.<_><_>3 4 4 20 -1.<_>3 4 2 10 2.<_>5 14 2 10 2.<_><_>14 0 6 9 -1.<_>16 0 2 9 3.<_><_>4 0 6 9 -1.<_>6 0 2 9 3.<_><_>4 5 18 5 -1.<_>10 5 6 5 3.<_><_>5 6 6 9 -1.<_>7 6 2 9 3.<_><_>7 2 15 8 -1.<_>12 2 5 8 3.<_><_>2 2 15 8 -1.<_>7 2 5 8 3.<_><_>10 0 4 9 -1.<_>10 0 2 9 2.<_><_>3 4 6 12 -1.<_>3 4 3 6 2.<_>6 10 3 6 2.<_><_>16 0 8 18 -1.<_>16 0 4 18 2.<_><_>0 0 8 18 -1.<_>4 0 4 18 2.<_><_>0 7 24 6 -1.<_>0 9 24 2 3.<_><_>4 7 14 3 -1.<_>11 7 7 3 2.<_><_>10 8 8 15 -1.<_>10 8 4 15 2.<_><_>7 0 10 14 -1.<_>12 0 5 14 2.<_><_>13 10 8 10 -1.<_>17 10 4 5 2.<_>13 15 4 5 2.<_><_>3 0 4 9 -1.<_>5 0 2 9 2.<_><_>16 1 6 8 -1.<_>16 1 3 8 2.<_><_>2 1 6 8 -1.<_>5 1 3 8 2.<_><_>3 6 18 12 -1.<_>3 10 18 4 3.<_><_>4 12 16 4 -1.<_>4 14 16 2 2.<_><_>4 9 16 15 -1.<_>4 14 16 5 3.<_><_>3 10 8 10 -1.<_>3 10 4 5 2.<_>7 15 4 5 2.<_><_>8 18 16 6 -1.<_>16 18 8 3 2.<_>8 21 8 3 2.<_><_>2 16 12 5 -1.<_>6 16 4 5 3.<_><_>14 14 9 4 -1.<_>14 16 9 2 2.<_><_>7 14 9 6 -1.<_>7 16 9 2 3.<_><_>4 10 16 12 -1.<_>4 14 16 4 3.<_><_>0 13 19 6 -1.<_>0 15 19 2 3.<_><_>10 13 9 6 -1.<_>10 15 9 2 3.<_><_>5 0 3 23 -1.<_>6 0 1 23 3.<_><_>0 8 24 6 -1.<_>0 10 24 2 3.<_><_>0 5 5 12 -1.<_>0 9 5 4 3.<_><_>3 0 19 18 -1.<_>3 9 19 9 2.<_><_>9 11 6 12 -1.<_>9 11 3 6 2.<_>12 17 3 6 2.<_><_>0 5 24 8 -1.<_>12 5 12 4 2.<_>0 9 12 4 2.<_><_>6 18 9 4 -1.<_>6 20 9 2 2.<_><_>8 8 10 6 -1.<_>8 10 10 2 3.<_><_>2 7 20 3 -1.<_>2 8 20 1 3.<_><_>12 0 7 20 -1.<_>12 10 7 10 2.<_><_>5 0 7 20 -1.<_>5 10 7 10 2.<_><_>14 2 2 18 -1.<_>14 11 2 9 2.<_><_>5 8 10 12 -1.<_>10 8 5 12 2.<_><_>6 9 12 8 -1.<_>12 9 6 4 2.<_>6 13 6 4 2.<_><_>7 7 3 14 -1.<_>7 14 3 7 2.<_><_>11 2 12 16 -1.<_>17 2 6 8 2.<_>11 10 6 8 2.<_><_>7 0 6 9 -1.<_>9 0 2 9 3.<_><_>13 14 9 4 -1.<_>13 16 9 2 2.<_><_>0 12 22 4 -1.<_>0 12 11 2 2.<_>11 14 11 2 2.<_><_>1 12 22 6 -1.<_>12 12 11 3 2.<_>1 15 11 3 2.<_><_>6 6 9 6 -1.<_>9 6 3 6 3.<_><_>10 0 4 9 -1.<_>10 0 2 9 2.<_><_>3 8 18 7 -1.<_>9 8 6 7 3.<_><_>0 6 24 6 -1.<_>0 8 24 2 3.<_><_>0 11 24 10 -1.<_>8 11 8 10 3.<_><_>3 3 18 21 -1.<_>9 3 6 21 3.<_><_>7 12 4 10 -1.<_>9 12 2 10 2.<_><_>10 16 10 8 -1.<_>15 16 5 4 2.<_>10 20 5 4 2.<_><_>8 6 6 9 -1.<_>10 6 2 9 3.<_><_>12 10 6 12 -1.<_>15 10 3 6 2.<_>12 16 3 6 2.<_><_>6 10 6 12 -1.<_>6 10 3 6 2.<_>9 16 3 6 2.<_><_>16 12 6 12 -1.<_>19 12 3 6 2.<_>16 18 3 6 2.<_><_>2 12 6 12 -1.<_>2 12 3 6 2.<_>5 18 3 6 2.<_><_>10 15 6 9 -1.<_>12 15 2 9 3.<_><_>8 15 6 9 -1.<_>10 15 2 9 3.<_><_>14 20 10 4 -1.<_>14 20 5 4 2.<_><_>0 20 10 4 -1.<_>5 20 5 4 2.<_><_>11 17 9 6 -1.<_>11 19 9 2 3.<_><_>3 2 14 4 -1.<_>3 4 14 2 2.<_><_>10 1 10 4 -1.<_>10 3 10 2 2.<_><_>0 15 10 4 -1.<_>5 15 5 4 2.<_><_>19 2 3 19 -1.<_>20 2 1 19 3.<_><_>4 12 9 8 -1.<_>7 12 3 8 3.<_><_>4 7 5 12 -1.<_>4 11 5 4 3.<_><_>0 1 24 3 -1.<_>8 1 8 3 3.<_><_>6 8 12 4 -1.<_>6 10 12 2 2.<_><_>19 3 4 10 -1.<_>19 3 2 10 2.<_><_>0 6 9 6 -1.<_>3 6 3 6 3.<_><_>18 0 6 22 -1.<_>20 0 2 22 3.<_><_>0 0 6 22 -1.<_>2 0 2 22 3.<_><_>5 15 19 3 -1.<_>5 16 19 1 3.<_><_>10 7 4 15 -1.<_>10 12 4 5 3.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>0 21 18 3 -1.<_>0 22 18 1 3.<_><_>7 3 10 15 -1.<_>7 8 10 5 3.<_><_>1 7 18 3 -1.<_>1 8 18 1 3.<_><_>8 2 9 6 -1.<_>11 2 3 6 3.<_><_>0 10 24 14 -1.<_>0 17 24 7 2.<_><_>13 9 8 10 -1.<_>17 9 4 5 2.<_>13 14 4 5 2.<_><_>10 5 4 9 -1.<_>12 5 2 9 2.<_><_>13 9 8 10 -1.<_>17 9 4 5 2.<_>13 14 4 5 2.<_><_>7 11 10 10 -1.<_>7 11 5 5 2.<_>12 16 5 5 2.<_><_>4 13 18 4 -1.<_>13 13 9 2 2.<_>4 15 9 2 2.<_><_>0 0 19 2 -1.<_>0 1 19 1 2.<_><_>0 18 24 6 -1.<_>8 18 8 6 3.<_><_>6 4 8 16 -1.<_>6 12 8 8 2.<_><_>7 8 10 4 -1.<_>7 10 10 2 2.<_><_>0 3 6 9 -1.<_>0 6 6 3 3.<_><_>13 15 7 9 -1.<_>13 18 7 3 3.<_><_>3 18 12 6 -1.<_>3 18 6 3 2.<_>9 21 6 3 2.<_><_>12 14 6 9 -1.<_>12 17 6 3 3.<_><_>2 15 15 8 -1.<_>2 19 15 4 2.<_><_>9 6 6 16 -1.<_>9 14 6 8 2.<_><_>6 6 7 12 -1.<_>6 10 7 4 3.<_><_>14 6 6 9 -1.<_>14 9 6 3 3.<_><_>5 14 6 9 -1.<_>5 17 6 3 3.<_><_>10 8 6 9 -1.<_>12 8 2 9 3.<_><_>6 6 4 18 -1.<_>6 6 2 9 2.<_>8 15 2 9 2.<_><_>14 9 6 12 -1.<_>17 9 3 6 2.<_>14 15 3 6 2.<_><_>4 9 6 12 -1.<_>4 9 3 6 2.<_>7 15 3 6 2.<_><_>14 15 9 6 -1.<_>14 17 9 2 3.<_><_>0 20 18 4 -1.<_>0 20 9 2 2.<_>9 22 9 2 2.<_><_>13 18 9 6 -1.<_>13 20 9 2 3.<_><_>2 18 9 6 -1.<_>2 20 9 2 3.<_><_>6 16 18 3 -1.<_>6 17 18 1 3.<_><_>0 16 18 3 -1.<_>0 17 18 1 3.<_><_>19 2 4 22 -1.<_>21 2 2 11 2.<_>19 13 2 11 2.<_><_>1 2 4 22 -1.<_>1 2 2 11 2.<_>3 13 2 11 2.<_><_>15 0 2 24 -1.<_>15 0 1 24 2.<_><_>3 20 16 4 -1.<_>11 20 8 4 2.<_><_>11 6 4 18 -1.<_>13 6 2 9 2.<_>11 15 2 9 2.<_><_>7 9 10 14 -1.<_>7 9 5 7 2.<_>12 16 5 7 2.<_><_>14 6 6 9 -1.<_>14 9 6 3 3.<_><_>3 6 7 9 -1.<_>3 9 7 3 3.<_><_>20 4 4 20 -1.<_>22 4 2 10 2.<_>20 14 2 10 2.<_><_>7 6 6 9 -1.<_>7 9 6 3 3.<_><_>7 0 10 14 -1.<_>12 0 5 7 2.<_>7 7 5 7 2.<_><_>2 1 18 6 -1.<_>11 1 9 6 2.<_><_>15 0 2 24 -1.<_>15 0 1 24 2.<_><_>7 0 2 24 -1.<_>8 0 1 24 2.<_><_>13 12 6 7 -1.<_>13 12 3 7 2.<_><_>5 12 6 7 -1.<_>8 12 3 7 2.<_><_>3 5 18 19 -1.<_>9 5 6 19 3.<_><_>5 6 9 6 -1.<_>8 6 3 6 3.<_><_>9 5 9 6 -1.<_>12 5 3 6 3.<_><_>3 16 10 8 -1.<_>3 16 5 4 2.<_>8 20 5 4 2.<_><_>19 8 5 15 -1.<_>19 13 5 5 3.<_><_>0 8 5 15 -1.<_>0 13 5 5 3.<_><_>20 4 4 20 -1.<_>22 4 2 10 2.<_>20 14 2 10 2.<_><_>0 4 4 20 -1.<_>0 4 2 10 2.<_>2 14 2 10 2.<_><_>7 7 10 4 -1.<_>7 7 5 4 2.<_><_>4 19 14 4 -1.<_>11 19 7 4 2.<_><_>10 11 12 3 -1.<_>10 11 6 3 2.<_><_>0 1 24 3 -1.<_>0 2 24 1 3.<_><_>7 2 14 20 -1.<_>14 2 7 10 2.<_>7 12 7 10 2.<_><_>0 13 6 9 -1.<_>2 13 2 9 3.<_><_>13 0 4 19 -1.<_>13 0 2 19 2.<_><_>1 11 14 3 -1.<_>8 11 7 3 2.<_><_>7 1 16 20 -1.<_>15 1 8 10 2.<_>7 11 8 10 2.<_><_>0 10 21 9 -1.<_>7 10 7 9 3.<_><_>6 19 15 5 -1.<_>11 19 5 5 3.<_><_>8 10 6 6 -1.<_>11 10 3 6 2.<_><_>7 1 16 20 -1.<_>15 1 8 10 2.<_>7 11 8 10 2.<_><_>1 1 16 20 -1.<_>1 1 8 10 2.<_>9 11 8 10 2.<_><_>16 4 3 12 -1.<_>16 10 3 6 2.<_><_>5 4 3 12 -1.<_>5 10 3 6 2.<_><_>7 6 10 8 -1.<_>12 6 5 4 2.<_>7 10 5 4 2.<_><_>4 9 6 6 -1.<_>4 12 6 3 2.<_><_>6 5 12 4 -1.<_>6 7 12 2 2.<_><_>9 2 5 15 -1.<_>9 7 5 5 3.<_><_>15 0 9 6 -1.<_>15 2 9 2 3.<_><_>6 0 11 10 -1.<_>6 5 11 5 2.<_><_>12 7 4 12 -1.<_>12 13 4 6 2.<_><_>7 2 9 4 -1.<_>7 4 9 2 2.<_><_>6 0 13 6 -1.<_>6 2 13 2 3.<_><_>10 6 4 18 -1.<_>10 6 2 9 2.<_>12 15 2 9 2.<_><_>10 8 6 9 -1.<_>12 8 2 9 3.<_><_>3 18 10 6 -1.<_>3 20 10 2 3.<_><_>4 14 20 3 -1.<_>4 15 20 1 3.<_><_>2 15 9 6 -1.<_>2 17 9 2 3.<_><_>13 0 4 19 -1.<_>13 0 2 19 2.<_><_>7 0 4 19 -1.<_>9 0 2 19 2.<_><_>1 4 22 2 -1.<_>1 5 22 1 2.<_><_>0 0 9 6 -1.<_>0 2 9 2 3.<_><_>0 0 24 18 -1.<_>0 9 24 9 2.<_><_>3 2 16 8 -1.<_>3 6 16 4 2.<_><_>3 6 18 6 -1.<_>3 8 18 2 3.<_><_>3 1 6 10 -1.<_>5 1 2 10 3.<_><_>13 0 9 6 -1.<_>16 0 3 6 3.<_><_>2 0 9 6 -1.<_>5 0 3 6 3.<_><_>10 2 4 15 -1.<_>10 7 4 5 3.<_><_>6 0 7 10 -1.<_>6 5 7 5 2.<_><_>2 2 20 4 -1.<_>12 2 10 2 2.<_>2 4 10 2 2.<_><_>2 11 19 3 -1.<_>2 12 19 1 3.<_><_>10 8 6 9 -1.<_>12 8 2 9 3.<_><_>8 8 6 9 -1.<_>10 8 2 9 3.<_><_>13 8 4 9 -1.<_>13 8 2 9 2.<_><_>3 11 9 9 -1.<_>6 11 3 9 3.<_><_>3 9 18 5 -1.<_>9 9 6 5 3.<_><_>2 4 2 20 -1.<_>2 14 2 10 2.<_><_>14 17 8 6 -1.<_>14 20 8 3 2.<_><_>3 21 18 2 -1.<_>3 22 18 1 2.<_><_>5 4 15 6 -1.<_>10 4 5 6 3.<_><_>2 15 12 6 -1.<_>2 17 12 2 3.<_><_>17 8 6 9 -1.<_>17 11 6 3 3.<_><_>2 12 20 4 -1.<_>2 12 10 2 2.<_>12 14 10 2 2.<_><_>0 17 24 6 -1.<_>0 19 24 2 3.<_><_>7 16 9 4 -1.<_>7 18 9 2 2.<_><_>15 1 4 22 -1.<_>17 1 2 11 2.<_>15 12 2 11 2.<_><_>5 1 4 22 -1.<_>5 1 2 11 2.<_>7 12 2 11 2.<_><_>11 13 8 9 -1.<_>11 16 8 3 3.<_><_>6 1 6 9 -1.<_>8 1 2 9 3.<_><_>11 4 3 18 -1.<_>11 10 3 6 3.<_><_>5 8 12 6 -1.<_>5 8 6 3 2.<_>11 11 6 3 2.<_><_>15 7 5 8 -1.<_>15 11 5 4 2.<_><_>4 7 5 8 -1.<_>4 11 5 4 2.<_><_>12 6 6 12 -1.<_>15 6 3 6 2.<_>12 12 3 6 2.<_><_>6 6 6 12 -1.<_>6 6 3 6 2.<_>9 12 3 6 2.<_><_>5 9 14 8 -1.<_>12 9 7 4 2.<_>5 13 7 4 2.<_><_>9 1 3 14 -1.<_>9 8 3 7 2.<_><_>12 6 6 12 -1.<_>12 10 6 4 3.<_><_>4 5 4 18 -1.<_>4 5 2 9 2.<_>6 14 2 9 2.<_><_>4 6 16 18 -1.<_>4 12 16 6 3.<_><_>5 4 7 20 -1.<_>5 14 7 10 2.<_><_>14 8 8 12 -1.<_>14 14 8 6 2.<_><_>9 10 6 14 -1.<_>9 10 3 7 2.<_>12 17 3 7 2.<_><_>9 5 9 6 -1.<_>12 5 3 6 3.<_><_>9 4 3 18 -1.<_>10 4 1 18 3.<_><_>1 4 22 14 -1.<_>12 4 11 7 2.<_>1 11 11 7 2.<_><_>2 7 18 2 -1.<_>2 8 18 1 2.<_><_>12 6 6 12 -1.<_>12 10 6 4 3.<_><_>6 5 9 7 -1.<_>9 5 3 7 3.<_><_>12 7 4 12 -1.<_>12 13 4 6 2.<_><_>8 7 4 12 -1.<_>8 13 4 6 2.<_><_>7 2 10 22 -1.<_>7 13 10 11 2.<_><_>0 1 3 20 -1.<_>1 1 1 20 3.<_><_>4 13 18 4 -1.<_>13 13 9 2 2.<_>4 15 9 2 2.<_><_>2 13 18 4 -1.<_>2 13 9 2 2.<_>11 15 9 2 2.<_><_>15 15 9 6 -1.<_>15 17 9 2 3.<_><_>0 15 9 6 -1.<_>0 17 9 2 3.<_><_>6 0 18 24 -1.<_>15 0 9 12 2.<_>6 12 9 12 2.<_><_>6 6 6 12 -1.<_>6 10 6 4 3.<_><_>8 7 10 4 -1.<_>8 9 10 2 2.<_><_>1 9 18 6 -1.<_>1 9 9 3 2.<_>10 12 9 3 2.<_><_>6 6 18 3 -1.<_>6 7 18 1 3.<_><_>7 7 9 8 -1.<_>10 7 3 8 3.<_><_>10 12 6 12 -1.<_>12 12 2 12 3.<_><_>3 14 18 3 -1.<_>3 15 18 1 3.<_><_>15 17 9 7 -1.<_>18 17 3 7 3.<_><_>1 12 10 6 -1.<_>1 14 10 2 3.<_><_>15 17 9 7 -1.<_>18 17 3 7 3.<_><_>10 3 3 19 -1.<_>11 3 1 19 3.<_><_>15 17 9 7 -1.<_>18 17 3 7 3.<_><_>6 1 11 9 -1.<_>6 4 11 3 3.<_><_>15 17 9 7 -1.<_>18 17 3 7 3.<_><_>6 5 11 6 -1.<_>6 8 11 3 2.<_><_>16 7 8 5 -1.<_>16 7 4 5 2.<_><_>2 4 20 19 -1.<_>12 4 10 19 2.<_><_>2 1 21 6 -1.<_>9 1 7 6 3.<_><_>6 5 12 14 -1.<_>6 5 6 7 2.<_>12 12 6 7 2.<_><_>9 0 6 9 -1.<_>11 0 2 9 3.<_><_>2 11 8 5 -1.<_>6 11 4 5 2.<_><_>16 7 8 5 -1.<_>16 7 4 5 2.<_><_>0 7 8 5 -1.<_>4 7 4 5 2.<_><_>15 17 9 7 -1.<_>18 17 3 7 3.<_><_>8 6 8 10 -1.<_>8 6 4 5 2.<_>12 11 4 5 2.<_><_>15 15 9 9 -1.<_>18 15 3 9 3.<_><_>0 15 9 9 -1.<_>3 15 3 9 3.<_><_>12 10 9 7 -1.<_>15 10 3 7 3.<_><_>3 10 9 7 -1.<_>6 10 3 7 3.<_><_>13 15 10 8 -1.<_>18 15 5 4 2.<_>13 19 5 4 2.<_><_>0 1 6 12 -1.<_>0 1 3 6 2.<_>3 7 3 6 2.<_><_>10 0 6 12 -1.<_>13 0 3 6 2.<_>10 6 3 6 2.<_><_>7 0 10 12 -1.<_>7 0 5 6 2.<_>12 6 5 6 2.<_><_>4 1 16 8 -1.<_>4 1 8 8 2.<_><_>0 21 19 3 -1.<_>0 22 19 1 3.<_><_>6 9 18 4 -1.<_>15 9 9 2 2.<_>6 11 9 2 2.<_><_>3 4 9 6 -1.<_>3 6 9 2 3.<_><_>9 1 6 15 -1.<_>9 6 6 5 3.<_><_>5 9 6 6 -1.<_>8 9 3 6 2.<_><_>5 1 14 9 -1.<_>5 4 14 3 3.<_><_>3 0 8 20 -1.<_>3 0 4 10 2.<_>7 10 4 10 2.<_><_>5 0 7 9 -1.<_>5 3 7 3 3.<_><_>6 6 12 5 -1.<_>10 6 4 5 3.<_><_>0 1 8 14 -1.<_>4 1 4 14 2.<_><_>2 12 22 4 -1.<_>2 14 22 2 2.<_><_>8 17 6 6 -1.<_>8 20 6 3 2.<_><_>18 1 6 7 -1.<_>18 1 3 7 2.<_><_>0 0 6 6 -1.<_>3 0 3 6 2.<_><_>4 6 17 18 -1.<_>4 12 17 6 3.<_><_>6 0 12 6 -1.<_>6 0 6 3 2.<_>12 3 6 3 2.<_><_>4 7 18 4 -1.<_>13 7 9 2 2.<_>4 9 9 2 2.<_><_>4 12 10 6 -1.<_>4 14 10 2 3.<_><_>7 9 10 12 -1.<_>12 9 5 6 2.<_>7 15 5 6 2.<_><_>0 1 24 3 -1.<_>8 1 8 3 3.<_><_>13 11 6 6 -1.<_>13 11 3 6 2.<_><_>5 11 6 6 -1.<_>8 11 3 6 2.<_><_>3 10 19 3 -1.<_>3 11 19 1 3.<_><_>0 2 6 9 -1.<_>0 5 6 3 3.<_><_>14 16 10 6 -1.<_>14 18 10 2 3.<_><_>0 16 10 6 -1.<_>0 18 10 2 3.<_><_>14 13 9 6 -1.<_>14 15 9 2 3.<_><_>0 16 18 3 -1.<_>0 17 18 1 3.<_><_>6 16 18 3 -1.<_>6 17 18 1 3.<_><_>0 18 9 6 -1.<_>0 20 9 2 3.<_><_>14 13 9 6 -1.<_>14 15 9 2 3.<_><_>6 2 6 9 -1.<_>8 2 2 9 3.<_><_>15 8 4 12 -1.<_>15 8 2 12 2.<_><_>8 13 8 8 -1.<_>8 17 8 4 2.<_><_>4 20 18 3 -1.<_>10 20 6 3 3.<_><_>5 8 4 12 -1.<_>7 8 2 12 2.<_><_>7 7 12 3 -1.<_>7 7 6 3 2.<_><_>10 6 4 9 -1.<_>12 6 2 9 2.<_><_>5 20 18 3 -1.<_>11 20 6 3 3.<_><_>1 20 18 3 -1.<_>7 20 6 3 3.<_><_>18 1 6 20 -1.<_>21 1 3 10 2.<_>18 11 3 10 2.<_><_>0 1 6 20 -1.<_>0 1 3 10 2.<_>3 11 3 10 2.<_><_>13 3 4 18 -1.<_>15 3 2 9 2.<_>13 12 2 9 2.<_><_>0 2 6 12 -1.<_>0 6 6 4 3.<_><_>12 9 12 6 -1.<_>18 9 6 3 2.<_>12 12 6 3 2.<_><_>7 3 4 18 -1.<_>7 3 2 9 2.<_>9 12 2 9 2.<_><_>14 0 6 9 -1.<_>16 0 2 9 3.<_><_>0 9 12 6 -1.<_>0 9 6 3 2.<_>6 12 6 3 2.<_><_>14 4 8 20 -1.<_>18 4 4 10 2.<_>14 14 4 10 2.<_><_>2 4 8 20 -1.<_>2 4 4 10 2.<_>6 14 4 10 2.<_><_>14 13 9 6 -1.<_>14 15 9 2 3.<_><_>1 13 9 6 -1.<_>1 15 9 2 3.<_><_>3 15 18 3 -1.<_>9 15 6 3 3.<_><_>5 13 9 6 -1.<_>5 15 9 2 3.<_><_>5 0 18 3 -1.<_>5 1 18 1 3.<_><_>8 2 6 7 -1.<_>11 2 3 7 2.<_><_>9 1 9 6 -1.<_>12 1 3 6 3.<_><_>6 1 9 6 -1.<_>9 1 3 6 3.<_><_>5 6 14 6 -1.<_>12 6 7 3 2.<_>5 9 7 3 2.<_><_>8 2 6 13 -1.<_>10 2 2 13 3.<_><_>6 11 12 6 -1.<_>12 11 6 3 2.<_>6 14 6 3 2.<_><_>3 1 18 15 -1.<_>9 1 6 15 3.<_><_>13 0 6 7 -1.<_>13 0 3 7 2.<_><_>3 3 16 6 -1.<_>3 6 16 3 2.<_><_>12 1 3 12 -1.<_>12 7 3 6 2.<_><_>7 7 6 9 -1.<_>9 7 2 9 3.<_><_>13 0 4 24 -1.<_>13 0 2 24 2.<_><_>7 0 4 24 -1.<_>9 0 2 24 2.<_><_>11 9 5 12 -1.<_>11 13 5 4 3.<_><_>7 15 9 6 -1.<_>7 17 9 2 3.<_><_>5 7 18 6 -1.<_>5 9 18 2 3.<_><_>8 9 5 12 -1.<_>8 13 5 4 3.<_><_>4 17 17 6 -1.<_>4 19 17 2 3.<_><_>0 3 18 14 -1.<_>0 3 9 7 2.<_>9 10 9 7 2.<_><_>0 1 24 2 -1.<_>0 2 24 1 2.<_><_>0 15 18 3 -1.<_>0 16 18 1 3.<_><_>9 0 6 9 -1.<_>11 0 2 9 3.<_><_>3 3 14 12 -1.<_>3 9 14 6 2.<_><_>12 1 3 12 -1.<_>12 7 3 6 2.<_><_>8 0 6 9 -1.<_>10 0 2 9 3.<_><_>10 6 6 10 -1.<_>12 6 2 10 3.<_><_>5 0 6 9 -1.<_>7 0 2 9 3.<_><_>2 0 21 7 -1.<_>9 0 7 7 3.<_><_>6 11 12 5 -1.<_>10 11 4 5 3.<_><_>8 7 9 8 -1.<_>11 7 3 8 3.<_><_>9 6 6 18 -1.<_>9 6 3 9 2.<_>12 15 3 9 2.<_><_>15 14 8 10 -1.<_>19 14 4 5 2.<_>15 19 4 5 2.<_><_>1 14 8 10 -1.<_>1 14 4 5 2.<_>5 19 4 5 2.<_><_>11 0 8 10 -1.<_>15 0 4 5 2.<_>11 5 4 5 2.<_><_>5 0 8 10 -1.<_>5 0 4 5 2.<_>9 5 4 5 2.<_><_>6 1 12 5 -1.<_>6 1 6 5 2.<_><_>1 12 18 2 -1.<_>10 12 9 2 2.<_><_>2 8 20 6 -1.<_>12 8 10 3 2.<_>2 11 10 3 2.<_><_>7 6 9 7 -1.<_>10 6 3 7 3.<_><_>10 5 8 16 -1.<_>14 5 4 8 2.<_>10 13 4 8 2.<_><_>3 9 16 8 -1.<_>3 9 8 4 2.<_>11 13 8 4 2.<_><_>7 8 10 4 -1.<_>7 8 5 4 2.<_><_>7 12 10 8 -1.<_>7 12 5 4 2.<_>12 16 5 4 2.<_><_>9 19 15 4 -1.<_>14 19 5 4 3.<_><_>1 0 18 9 -1.<_>7 0 6 9 3.<_><_>13 4 10 8 -1.<_>18 4 5 4 2.<_>13 8 5 4 2.<_><_>3 16 18 4 -1.<_>9 16 6 4 3.<_><_>8 7 10 12 -1.<_>13 7 5 6 2.<_>8 13 5 6 2.<_><_>6 7 10 12 -1.<_>6 7 5 6 2.<_>11 13 5 6 2.<_><_>4 6 18 7 -1.<_>10 6 6 7 3.<_><_>0 17 18 3 -1.<_>0 18 18 1 3.<_><_>3 17 18 3 -1.<_>3 18 18 1 3.<_><_>2 4 6 10 -1.<_>4 4 2 10 3.<_><_>16 0 8 24 -1.<_>16 0 4 24 2.<_><_>4 0 8 15 -1.<_>8 0 4 15 2.<_><_>16 0 8 24 -1.<_>16 0 4 24 2.<_><_>1 4 18 9 -1.<_>7 4 6 9 3.<_><_>15 12 9 6 -1.<_>15 14 9 2 3.<_><_>3 9 18 6 -1.<_>3 9 9 3 2.<_>12 12 9 3 2.<_><_>18 5 6 9 -1.<_>18 8 6 3 3.<_><_>0 5 6 9 -1.<_>0 8 6 3 3.<_><_>4 7 18 4 -1.<_>13 7 9 2 2.<_>4 9 9 2 2.<_><_>2 1 12 20 -1.<_>2 1 6 10 2.<_>8 11 6 10 2.<_><_>17 0 6 23 -1.<_>17 0 3 23 2.<_><_>1 6 2 18 -1.<_>1 15 2 9 2.<_><_>8 8 10 6 -1.<_>8 10 10 2 3.<_><_>0 6 20 6 -1.<_>0 6 10 3 2.<_>10 9 10 3 2.<_><_>11 12 12 5 -1.<_>15 12 4 5 3.<_><_>0 4 3 19 -1.<_>1 4 1 19 3.<_><_>19 1 3 18 -1.<_>20 1 1 18 3.<_><_>2 1 3 18 -1.<_>3 1 1 18 3.<_><_>3 10 18 3 -1.<_>9 10 6 3 3.<_><_>4 4 10 9 -1.<_>9 4 5 9 2.<_><_>7 13 14 7 -1.<_>7 13 7 7 2.<_><_>3 13 14 7 -1.<_>10 13 7 7 2.<_><_>8 15 9 6 -1.<_>11 15 3 6 3.<_><_>4 14 8 10 -1.<_>4 14 4 5 2.<_>8 19 4 5 2.<_><_>10 14 4 10 -1.<_>10 19 4 5 2.<_><_>3 8 5 16 -1.<_>3 16 5 8 2.<_><_>15 10 9 6 -1.<_>15 12 9 2 3.<_><_>0 10 9 6 -1.<_>0 12 9 2 3.<_><_>6 7 12 9 -1.<_>6 10 12 3 3.<_><_>9 10 5 8 -1.<_>9 14 5 4 2.<_><_>12 1 3 12 -1.<_>12 7 3 6 2.<_><_>8 15 6 9 -1.<_>10 15 2 9 3.<_><_>16 6 7 6 -1.<_>16 9 7 3 2.<_><_>8 1 4 22 -1.<_>10 1 2 22 2.<_><_>6 6 14 3 -1.<_>6 6 7 3 2.<_><_>0 18 19 3 -1.<_>0 19 19 1 3.<_><_>17 0 6 24 -1.<_>17 0 3 24 2.<_><_>0 13 15 6 -1.<_>5 13 5 6 3.<_><_>9 6 10 14 -1.<_>14 6 5 7 2.<_>9 13 5 7 2.<_><_>1 6 8 10 -1.<_>1 6 4 5 2.<_>5 11 4 5 2.<_><_>7 6 12 5 -1.<_>7 6 6 5 2.<_><_>7 7 9 6 -1.<_>10 7 3 6 3.<_><_>7 8 14 14 -1.<_>14 8 7 7 2.<_>7 15 7 7 2.<_><_>3 8 14 14 -1.<_>3 8 7 7 2.<_>10 15 7 7 2.<_><_>9 8 13 4 -1.<_>9 10 13 2 2.<_><_>3 2 6 12 -1.<_>3 2 3 6 2.<_>6 8 3 6 2.<_><_>6 10 17 6 -1.<_>6 13 17 3 2.<_><_>1 10 17 6 -1.<_>1 13 17 3 2.<_><_>16 7 8 9 -1.<_>16 10 8 3 3.<_><_>0 7 8 9 -1.<_>0 10 8 3 3.<_><_>0 9 24 10 -1.<_>12 9 12 5 2.<_>0 14 12 5 2.<_><_>3 2 15 8 -1.<_>8 2 5 8 3.<_><_>4 2 18 8 -1.<_>10 2 6 8 3.<_><_>0 1 18 4 -1.<_>0 1 9 2 2.<_>9 3 9 2 2.<_><_>20 2 3 18 -1.<_>21 2 1 18 3.<_><_>1 3 3 19 -1.<_>2 3 1 19 3.<_><_>18 8 6 16 -1.<_>20 8 2 16 3.<_><_>0 8 6 16 -1.<_>2 8 2 16 3.<_><_>8 18 11 6 -1.<_>8 20 11 2 3.<_><_>4 6 12 5 -1.<_>8 6 4 5 3.<_><_>7 6 12 5 -1.<_>11 6 4 5 3.<_><_>6 3 9 6 -1.<_>9 3 3 6 3.<_><_>7 6 12 5 -1.<_>7 6 6 5 2.<_><_>9 8 6 7 -1.<_>12 8 3 7 2.<_><_>8 2 9 6 -1.<_>11 2 3 6 3.<_><_>8 14 6 9 -1.<_>8 17 6 3 3.<_><_>8 2 9 6 -1.<_>11 2 3 6 3.<_><_>4 3 16 20 -1.<_>4 3 8 10 2.<_>12 13 8 10 2.<_><_>7 6 10 12 -1.<_>12 6 5 6 2.<_>7 12 5 6 2.<_><_>0 2 7 12 -1.<_>0 6 7 4 3.<_><_>12 17 11 6 -1.<_>12 19 11 2 3.<_><_>4 7 12 8 -1.<_>4 7 6 4 2.<_>10 11 6 4 2.<_><_>8 11 8 10 -1.<_>12 11 4 5 2.<_>8 16 4 5 2.<_><_>9 1 4 9 -1.<_>11 1 2 9 2.<_><_>14 0 3 22 -1.<_>15 0 1 22 3.<_><_>7 0 3 22 -1.<_>8 0 1 22 3.<_><_>4 7 18 4 -1.<_>13 7 9 2 2.<_>4 9 9 2 2.<_><_>10 2 4 15 -1.<_>10 7 4 5 3.<_><_>12 1 3 12 -1.<_>12 7 3 6 2.<_><_>0 0 18 13 -1.<_>9 0 9 13 2.<_><_>16 0 3 24 -1.<_>17 0 1 24 3.<_><_>5 0 3 24 -1.<_>6 0 1 24 3.<_><_>10 15 5 8 -1.<_>10 19 5 4 2.<_><_>2 18 18 2 -1.<_>2 19 18 1 2.<_><_>2 8 20 3 -1.<_>2 9 20 1 3.<_><_>7 6 9 6 -1.<_>7 8 9 2 3.<_><_>3 2 19 10 -1.<_>3 7 19 5 2.<_><_>2 7 19 3 -1.<_>2 8 19 1 3.<_><_>15 6 9 4 -1.<_>15 8 9 2 2.<_><_>2 2 18 8 -1.<_>8 2 6 8 3.<_><_>10 9 14 4 -1.<_>10 9 7 4 2.<_><_>4 4 6 16 -1.<_>7 4 3 16 2.<_><_>15 8 9 16 -1.<_>18 8 3 16 3.<_><_>0 8 9 16 -1.<_>3 8 3 16 3.<_><_>18 0 6 14 -1.<_>20 0 2 14 3.<_><_>0 0 6 14 -1.<_>2 0 2 14 3.<_><_>15 0 6 22 -1.<_>17 0 2 22 3.<_><_>3 0 6 22 -1.<_>5 0 2 22 3.<_><_>12 2 12 20 -1.<_>16 2 4 20 3.<_><_>0 2 12 20 -1.<_>4 2 4 20 3.<_><_>11 6 4 9 -1.<_>11 6 2 9 2.<_><_>9 0 6 16 -1.<_>12 0 3 16 2.<_><_>12 1 3 12 -1.<_>12 7 3 6 2.<_><_>3 4 18 6 -1.<_>3 4 9 3 2.<_>12 7 9 3 2.<_><_>5 5 16 8 -1.<_>13 5 8 4 2.<_>5 9 8 4 2.<_><_>0 13 10 6 -1.<_>0 15 10 2 3.<_><_>8 14 9 6 -1.<_>8 16 9 2 3.<_><_>6 2 9 6 -1.<_>9 2 3 6 3.<_><_>14 1 10 8 -1.<_>19 1 5 4 2.<_>14 5 5 4 2.<_><_>9 1 3 12 -1.<_>9 7 3 6 2.<_><_>6 4 12 9 -1.<_>6 7 12 3 3.<_><_>6 5 12 6 -1.<_>10 5 4 6 3.<_><_>1 1 8 5 -1.<_>5 1 4 5 2.<_><_>12 12 6 8 -1.<_>12 16 6 4 2.<_><_>3 12 12 6 -1.<_>3 14 12 2 3.<_><_>9 18 12 6 -1.<_>15 18 6 3 2.<_>9 21 6 3 2.<_><_>4 13 6 6 -1.<_>4 16 6 3 2.<_><_>11 3 7 18 -1.<_>11 12 7 9 2.<_><_>3 9 18 3 -1.<_>9 9 6 3 3.<_><_>5 3 19 2 -1.<_>5 4 19 1 2.<_><_>4 2 12 6 -1.<_>4 2 6 3 2.<_>10 5 6 3 2.<_><_>9 6 6 9 -1.<_>11 6 2 9 3.<_><_>8 6 6 9 -1.<_>10 6 2 9 3.<_><_>16 9 5 15 -1.<_>16 14 5 5 3.<_><_>3 9 5 15 -1.<_>3 14 5 5 3.<_><_>6 6 14 6 -1.<_>13 6 7 3 2.<_>6 9 7 3 2.<_><_>8 6 3 14 -1.<_>8 13 3 7 2.<_><_>0 16 24 5 -1.<_>8 16 8 5 3.<_><_>0 20 20 3 -1.<_>10 20 10 3 2.<_><_>5 10 18 2 -1.<_>5 11 18 1 2.<_><_>0 6 6 10 -1.<_>2 6 2 10 3.<_><_>2 1 20 3 -1.<_>2 2 20 1 3.<_><_>9 13 6 11 -1.<_>11 13 2 11 3.<_><_>9 15 6 8 -1.<_>9 19 6 4 2.<_><_>9 12 6 9 -1.<_>9 15 6 3 3.<_><_>5 11 18 2 -1.<_>5 12 18 1 2.<_><_>2 6 15 6 -1.<_>2 8 15 2 3.<_><_>6 0 18 3 -1.<_>6 1 18 1 3.<_><_>5 0 3 18 -1.<_>6 0 1 18 3.<_><_>18 3 6 10 -1.<_>20 3 2 10 3.<_><_>0 3 6 10 -1.<_>2 3 2 10 3.<_><_>10 5 8 9 -1.<_>10 5 4 9 2.<_><_>6 5 8 9 -1.<_>10 5 4 9 2.<_><_>3 2 20 3 -1.<_>3 3 20 1 3.<_><_>5 2 13 4 -1.<_>5 4 13 2 2.<_><_>17 0 7 14 -1.<_>17 7 7 7 2.<_><_>0 0 7 14 -1.<_>0 7 7 7 2.<_><_>9 11 10 6 -1.<_>9 11 5 6 2.<_><_>5 11 10 6 -1.<_>10 11 5 6 2.<_><_>11 6 3 18 -1.<_>11 12 3 6 3.<_><_>0 16 18 3 -1.<_>0 17 18 1 3.<_><_>6 16 18 3 -1.<_>6 17 18 1 3.<_><_>4 6 9 10 -1.<_>4 11 9 5 2.<_><_>9 7 15 4 -1.<_>9 9 15 2 2.<_><_>5 6 12 6 -1.<_>5 6 6 3 2.<_>11 9 6 3 2.<_><_>6 1 12 9 -1.<_>6 4 12 3 3.<_><_>7 9 6 12 -1.<_>7 9 3 6 2.<_>10 15 3 6 2.<_><_>11 5 13 6 -1.<_>11 7 13 2 3.<_><_>1 11 22 13 -1.<_>12 11 11 13 2.<_><_>18 8 6 6 -1.<_>18 11 6 3 2.<_><_>0 8 6 6 -1.<_>0 11 6 3 2.<_><_>0 6 24 3 -1.<_>0 7 24 1 3.<_><_>0 5 10 6 -1.<_>0 7 10 2 3.<_><_>6 7 18 3 -1.<_>6 8 18 1 3.<_><_>0 0 10 6 -1.<_>0 2 10 2 3.<_><_>19 0 3 19 -1.<_>20 0 1 19 3.<_><_>4 6 12 16 -1.<_>4 6 6 8 2.<_>10 14 6 8 2.<_><_>19 6 4 18 -1.<_>21 6 2 9 2.<_>19 15 2 9 2.<_><_>1 6 4 18 -1.<_>1 6 2 9 2.<_>3 15 2 9 2.<_><_>3 21 18 3 -1.<_>3 22 18 1 3.<_><_>0 19 9 4 -1.<_>0 21 9 2 2.<_><_>12 18 12 6 -1.<_>18 18 6 3 2.<_>12 21 6 3 2.<_><_>7 18 9 4 -1.<_>7 20 9 2 2.<_><_>12 16 10 8 -1.<_>17 16 5 4 2.<_>12 20 5 4 2.<_><_>2 16 10 8 -1.<_>2 16 5 4 2.<_>7 20 5 4 2.<_><_>14 0 10 12 -1.<_>19 0 5 6 2.<_>14 6 5 6 2.<_><_>0 0 10 12 -1.<_>0 0 5 6 2.<_>5 6 5 6 2.<_><_>15 14 9 6 -1.<_>15 16 9 2 3.<_><_>0 14 9 6 -1.<_>0 16 9 2 3.<_><_>14 14 10 6 -1.<_>14 16 10 2 3.<_><_>0 14 10 6 -1.<_>0 16 10 2 3.<_><_>5 18 18 2 -1.<_>5 19 18 1 2.<_><_>0 18 18 3 -1.<_>0 19 18 1 3.<_><_>3 5 18 12 -1.<_>12 5 9 6 2.<_>3 11 9 6 2.<_><_>5 3 7 9 -1.<_>5 6 7 3 3.<_><_>4 0 19 15 -1.<_>4 5 19 5 3.<_><_>3 0 16 4 -1.<_>3 2 16 2 2.<_><_>4 12 16 12 -1.<_>4 12 8 12 2.<_><_>4 3 12 15 -1.<_>10 3 6 15 2.<_><_>16 4 2 19 -1.<_>16 4 1 19 2.<_><_>6 4 2 19 -1.<_>7 4 1 19 2.<_><_>13 14 8 10 -1.<_>17 14 4 5 2.<_>13 19 4 5 2.<_><_>3 14 8 10 -1.<_>3 14 4 5 2.<_>7 19 4 5 2.<_><_>12 6 3 18 -1.<_>12 12 3 6 3.<_><_>5 11 12 6 -1.<_>5 11 6 3 2.<_>11 14 6 3 2.<_><_>10 5 8 10 -1.<_>14 5 4 5 2.<_>10 10 4 5 2.<_><_>6 4 12 10 -1.<_>6 4 6 5 2.<_>12 9 6 5 2.<_><_>6 8 18 10 -1.<_>15 8 9 5 2.<_>6 13 9 5 2.<_><_>0 8 18 10 -1.<_>0 8 9 5 2.<_>9 13 9 5 2.<_><_>12 6 3 18 -1.<_>12 12 3 6 3.<_><_>0 14 18 3 -1.<_>0 15 18 1 3.<_><_>12 6 3 18 -1.<_>12 12 3 6 3.<_><_>9 6 3 18 -1.<_>9 12 3 6 3.<_><_>6 14 18 3 -1.<_>6 15 18 1 3.<_><_>0 5 18 3 -1.<_>0 6 18 1 3.<_><_>2 5 22 3 -1.<_>2 6 22 1 3.<_><_>0 0 21 10 -1.<_>7 0 7 10 3.<_><_>6 3 18 17 -1.<_>12 3 6 17 3.<_><_>0 3 18 17 -1.<_>6 3 6 17 3.<_><_>0 12 24 11 -1.<_>8 12 8 11 3.<_><_>4 10 16 6 -1.<_>4 13 16 3 2.<_><_>12 8 6 8 -1.<_>12 12 6 4 2.<_><_>6 14 8 7 -1.<_>10 14 4 7 2.<_><_>15 10 6 14 -1.<_>18 10 3 7 2.<_>15 17 3 7 2.<_><_>3 10 6 14 -1.<_>3 10 3 7 2.<_>6 17 3 7 2.<_><_>6 12 18 2 -1.<_>6 13 18 1 2.<_><_>5 8 10 6 -1.<_>5 10 10 2 3.<_><_>12 11 9 4 -1.<_>12 13 9 2 2.<_><_>0 11 9 6 -1.<_>0 13 9 2 3.<_><_>11 2 3 18 -1.<_>12 2 1 18 3.<_><_>10 2 3 18 -1.<_>11 2 1 18 3.<_><_>9 12 6 10 -1.<_>11 12 2 10 3.<_><_>1 10 6 9 -1.<_>1 13 6 3 3.<_><_>6 9 16 6 -1.<_>14 9 8 3 2.<_>6 12 8 3 2.<_><_>1 8 9 6 -1.<_>1 10 9 2 3.<_><_>7 7 16 6 -1.<_>7 9 16 2 3.<_><_>0 0 18 3 -1.<_>0 1 18 1 3.<_><_>10 0 6 9 -1.<_>12 0 2 9 3.<_><_>9 5 6 6 -1.<_>12 5 3 6 2.<_><_>10 6 4 18 -1.<_>12 6 2 9 2.<_>10 15 2 9 2.<_><_>8 0 6 9 -1.<_>10 0 2 9 3.<_><_>9 1 6 9 -1.<_>9 4 6 3 3.<_><_>1 0 18 9 -1.<_>1 3 18 3 3.<_><_>0 3 24 3 -1.<_>0 4 24 1 3.<_><_>6 14 9 4 -1.<_>6 16 9 2 2.<_><_>8 9 8 10 -1.<_>12 9 4 5 2.<_>8 14 4 5 2.<_><_>5 2 13 9 -1.<_>5 5 13 3 3.<_><_>4 4 16 9 -1.<_>4 7 16 3 3.<_><_>4 4 14 9 -1.<_>4 7 14 3 3.<_><_>8 5 9 6 -1.<_>8 7 9 2 3.<_><_>1 7 16 6 -1.<_>1 9 16 2 3.<_><_>10 5 13 9 -1.<_>10 8 13 3 3.<_><_>1 5 13 9 -1.<_>1 8 13 3 3.<_><_>0 4 24 6 -1.<_>12 4 12 3 2.<_>0 7 12 3 2.<_><_>1 14 10 9 -1.<_>1 17 10 3 3.<_><_>5 17 18 3 -1.<_>5 18 18 1 3.<_><_>0 16 18 3 -1.<_>0 17 18 1 3.<_><_>9 17 9 6 -1.<_>9 19 9 2 3.<_><_>1 20 22 4 -1.<_>1 20 11 2 2.<_>12 22 11 2 2.<_><_>8 14 8 6 -1.<_>8 17 8 3 2.<_><_>8 6 8 15 -1.<_>8 11 8 5 3.<_><_>5 4 18 3 -1.<_>5 5 18 1 3.<_><_>9 3 5 10 -1.<_>9 8 5 5 2.<_><_>6 8 12 3 -1.<_>6 8 6 3 2.<_><_>2 6 18 6 -1.<_>2 6 9 3 2.<_>11 9 9 3 2.<_><_>10 6 4 18 -1.<_>12 6 2 9 2.<_>10 15 2 9 2.<_><_>7 5 6 6 -1.<_>10 5 3 6 2.<_><_>14 5 2 18 -1.<_>14 14 2 9 2.<_><_>8 5 2 18 -1.<_>8 14 2 9 2.<_><_>9 2 10 6 -1.<_>9 2 5 6 2.<_><_>3 1 18 12 -1.<_>12 1 9 12 2.<_><_>5 2 17 22 -1.<_>5 13 17 11 2.<_><_>4 0 12 6 -1.<_>4 2 12 2 3.<_><_>6 9 16 6 -1.<_>14 9 8 3 2.<_>6 12 8 3 2.<_><_>9 0 5 18 -1.<_>9 9 5 9 2.<_><_>12 0 6 9 -1.<_>14 0 2 9 3.<_><_>6 0 6 9 -1.<_>8 0 2 9 3.<_><_>9 1 6 12 -1.<_>11 1 2 12 3.<_><_>5 9 13 4 -1.<_>5 11 13 2 2.<_><_>5 8 19 3 -1.<_>5 9 19 1 3.<_><_>9 9 6 8 -1.<_>9 13 6 4 2.<_><_>11 9 4 15 -1.<_>11 14 4 5 3.<_><_>2 0 6 14 -1.<_>2 0 3 7 2.<_>5 7 3 7 2.<_><_>15 1 6 14 -1.<_>18 1 3 7 2.<_>15 8 3 7 2.<_><_>3 1 6 14 -1.<_>3 1 3 7 2.<_>6 8 3 7 2.<_><_>3 20 18 4 -1.<_>12 20 9 2 2.<_>3 22 9 2 2.<_><_>5 0 4 20 -1.<_>5 0 2 10 2.<_>7 10 2 10 2.<_><_>16 8 8 12 -1.<_>20 8 4 6 2.<_>16 14 4 6 2.<_><_>0 8 8 12 -1.<_>0 8 4 6 2.<_>4 14 4 6 2.<_><_>13 13 10 8 -1.<_>18 13 5 4 2.<_>13 17 5 4 2.<_><_>1 13 10 8 -1.<_>1 13 5 4 2.<_>6 17 5 4 2.<_><_>15 8 4 15 -1.<_>15 13 4 5 3.<_><_>5 8 4 15 -1.<_>5 13 4 5 3.<_><_>6 11 16 12 -1.<_>6 15 16 4 3.<_><_>2 11 16 12 -1.<_>2 15 16 4 3.<_><_>14 12 7 9 -1.<_>14 15 7 3 3.<_><_>10 1 3 21 -1.<_>10 8 3 7 3.<_><_>13 11 9 4 -1.<_>13 13 9 2 2.<_><_>3 10 17 9 -1.<_>3 13 17 3 3.<_><_>13 8 8 15 -1.<_>13 13 8 5 3.<_><_>3 8 8 15 -1.<_>3 13 8 5 3.<_><_>11 14 10 8 -1.<_>16 14 5 4 2.<_>11 18 5 4 2.<_><_>0 18 22 6 -1.<_>0 18 11 3 2.<_>11 21 11 3 2.<_><_>0 16 24 4 -1.<_>0 16 12 4 2.<_><_>6 20 12 3 -1.<_>12 20 6 3 2.<_><_>18 12 6 12 -1.<_>21 12 3 6 2.<_>18 18 3 6 2.<_><_>0 12 6 12 -1.<_>0 12 3 6 2.<_>3 18 3 6 2.<_><_>15 17 9 6 -1.<_>15 19 9 2 3.<_><_>1 6 22 10 -1.<_>1 6 11 5 2.<_>12 11 11 5 2.<_><_>15 17 9 6 -1.<_>15 19 9 2 3.<_><_>0 18 18 2 -1.<_>0 19 18 1 2.<_><_>3 15 19 3 -1.<_>3 16 19 1 3.<_><_>0 13 18 3 -1.<_>0 14 18 1 3.<_><_>15 17 9 6 -1.<_>15 19 9 2 3.<_><_>0 17 9 6 -1.<_>0 19 9 2 3.<_><_>12 17 9 6 -1.<_>12 19 9 2 3.<_><_>3 17 9 6 -1.<_>3 19 9 2 3.<_><_>16 2 3 20 -1.<_>17 2 1 20 3.<_><_>0 13 24 8 -1.<_>0 17 24 4 2.<_><_>9 1 6 22 -1.<_>12 1 3 11 2.<_>9 12 3 11 2. \ No newline at end of file diff --git a/face_detection/main.py b/face_detection/main.py index e8415a1f0..ebe2992cb 100644 --- a/face_detection/main.py +++ b/face_detection/main.py @@ -1,32 +1,32 @@ -import cv2 - -faceCascade = cv2.CascadeClassifier("haarcascade.xml") - -video_capture = cv2.VideoCapture(0) - -while True: - # Capture frame-by-frame - ret, frame = video_capture.read() - - gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) - - faces = faceCascade.detectMultiScale( - gray, - scaleFactor=1.1, - minNeighbors=5, - minSize=(30, 30) - ) - - # Draw a rectangle around the faces - for (x, y, w, h) in faces: - cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) - - # Display the resulting frame - cv2.imshow('Video', frame) - - if cv2.waitKey(1) & 0xFF == ord('q'): - break - -# When everything is done, release the capture -video_capture.release() -cv2.destroyAllWindows() +import cv2 + +faceCascade = cv2.CascadeClassifier("haarcascade.xml") + +video_capture = cv2.VideoCapture(0) + +while True: + # Capture frame-by-frame + ret, frame = video_capture.read() + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + + faces = faceCascade.detectMultiScale( + gray, + scaleFactor=1.1, + minNeighbors=5, + minSize=(30, 30) + ) + + # Draw a rectangle around the faces + for (x, y, w, h) in faces: + cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) + + # Display the resulting frame + cv2.imshow('Video', frame) + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + +# When everything is done, release the capture +video_capture.release() +cv2.destroyAllWindows() diff --git a/face_detection/makefile b/face_detection/makefile index e78e53c81..7aafa604a 100644 --- a/face_detection/makefile +++ b/face_detection/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/face_morpher/README.md b/face_morpher/README.md index 28e97fb72..f8c10690d 100644 --- a/face_morpher/README.md +++ b/face_morpher/README.md @@ -1,35 +1,35 @@ -# Face-Morphing - -The script is used to do face morphing of 3 famous USA Presidents by creating a small gif converting one face to another (One can use Delaunay triangulation+ Warp affine and cv2 -module for this.The visuals of the script is being provided below , The steps or the approach the script is following is mentioned below : -``` -Step1 : First Download the script -Step2 : Or you can directly clone the script from here -Step3 : Then directly input your images from this section : - if __name__ == '__main__': - filename1 = r"C:\Users\Anustup\Desktop\Facemorph\hilary_clinton.jpg" - filename2 = r"C:\Users\Anustup\Desktop\Facemorph\ted_cruz.jpg" - alpha = 0.5 -Step 4 : You can directly add your image files here -Step 5 : Now simply add some TXT files that have facial landmarks , you can use any prebuild data sets or any online source to extract txt files for extarcting the landmarks -Step 6 : Simply add that TXT files to it -Step 7 : Run the Script you can see the Output -``` -You can see your output in a pop uped window . - -### How to Run the Script : - -To run the script use the following command line : -``` -python run requirements.txt -``` -Or you can use pip or conda command to do so : -``` -pip install sys numpy cv2 -conda install sys numpy cv2 -``` -### Output : - -Here you can see what are the input images in one side and out put face morphed image on the other side - -![alt text](https://github.com/Anustup900/Automation-scripts/blob/main/facemorphing/Assets/abc.PNG) +# Face-Morphing + +The script is used to do face morphing of 3 famous USA Presidents by creating a small gif converting one face to another (One can use Delaunay triangulation+ Warp affine and cv2 +module for this.The visuals of the script is being provided below , The steps or the approach the script is following is mentioned below : +``` +Step1 : First Download the script +Step2 : Or you can directly clone the script from here +Step3 : Then directly input your images from this section : + if __name__ == '__main__': + filename1 = r"C:\Users\Anustup\Desktop\Facemorph\hilary_clinton.jpg" + filename2 = r"C:\Users\Anustup\Desktop\Facemorph\ted_cruz.jpg" + alpha = 0.5 +Step 4 : You can directly add your image files here +Step 5 : Now simply add some TXT files that have facial landmarks , you can use any prebuild data sets or any online source to extract txt files for extarcting the landmarks +Step 6 : Simply add that TXT files to it +Step 7 : Run the Script you can see the Output +``` +You can see your output in a pop uped window . + +### How to Run the Script : + +To run the script use the following command line : +``` +python run requirements.txt +``` +Or you can use pip or conda command to do so : +``` +pip install sys numpy cv2 +conda install sys numpy cv2 +``` +### Output : + +Here you can see what are the input images in one side and out put face morphed image on the other side + +![alt text](https://github.com/Anustup900/Automation-scripts/blob/main/facemorphing/Assets/abc.PNG) diff --git a/face_morpher/facemorphing.py b/face_morpher/facemorphing.py index de4382927..6a9493805 100644 --- a/face_morpher/facemorphing.py +++ b/face_morpher/facemorphing.py @@ -1,97 +1,97 @@ -import numpy as np -import cv2 -# import sys -# Read points from text file - - -def readPoints(path): - # Create array of points - points = [] - # Read points - with open(path) as file: - for line in file: - x, y = line.split() - points.append((int(x), int(y))) - - return points - -# Apply affine transform calculated using srcTri and dstTri to src and -# output an image of size. - - -def applyAffineTransform(src, srcTri, dstTri, size): - # Given a pair of triangles, find the affine transform. - warpMat = cv2.getAffineTransform(np.float32(srcTri), np.float32(dstTri)) - # Apply the Affine Transform just found to the src image - dst = cv2.warpAffine(src, warpMat, (size[0], size[1]), None, - flags=cv2.INTER_LINEAR, - borderMode=cv2.BORDER_REFLECT_101) - return dst - - -# Warps and alpha blends triangular regions from img1 and img2 to img -def morphTriangle(img1, img2, img, t1, t2, t, alpha): - - # Find bounding rectangle for each triangle - r1 = cv2.boundingRect(np.float32([t1])) - r2 = cv2.boundingRect(np.float32([t2])) - r = cv2.boundingRect(np.float32([t])) - # Offset points by left top corner of the respective rectangles - t1Rect = [] - t2Rect = [] - tRect = [] - for i in range(0, 3): - tRect.append(((t[i][0] - r[0]), (t[i][1] - r[1]))) - t1Rect.append(((t1[i][0] - r1[0]), (t1[i][1] - r1[1]))) - t2Rect.append(((t2[i][0] - r2[0]), (t2[i][1] - r2[1]))) - mask = np . zeros((r[3], r[2], 3), dtype=np . float32) - cv2.fillConvexPoly(mask, np.int32(tRect), (1.0, 1.0, 1.0), 16, 0) - # Apply warpImage to small rectangular patches - img1Rect = img1[r1[1]:r1[1] + r1[3], r1[0]:r1[0] + r1[2]] - img2Rect = img2[r2[1]:r2[1] + r2[3], r2[0]:r2[0] + r2[2]] - size = (r[2], r[3]) - warpImage1 = applyAffineTransform(img1Rect, t1Rect, tRect, size) - warpImage2 = applyAffineTransform(img2Rect, t2Rect, tRect, size) - - # Alpha blend rectangular patches - imgRect = (1.0 - alpha) * warpImage1 + alpha * warpImage2 - - # Copy triangular region of the rectangular patch to the output image - img[r[1]: r[1] + r[3], r[0]: r[0] + r[2]] - img[r[1]: r[1] + r[3], r[0]: r[0] + r[2]] * (1 - mask) + imgRect * mask - - -if __name__ == '__main__': - filename1 = r"C:\Users\Anustup\Desktop\Facemorph\hilary_clinton.jpg" - filename2 = r"C:\Users\Anustup\Desktop\Facemorph\ted_cruz.jpg" - alpha = 0.5 - # Read images - img1 = cv2.imread(filename1) - img2 = cv2.imread(filename2) - # Convert Mat to float data type - img1 = np.float32(img1) - img2 = np.float32(img2) - # Read array of corresponding points - points1 = readPoints(filename1 + '.txt') - points2 = readPoints(filename2 + '.txt') - points = [] - # Compute weighted average point coordinates - for i in range(0, len(points1)): - x = (1 - alpha) * points1[i][0] + alpha * points2[i][0] - y = (1 - alpha) * points1[i][1] + alpha * points2[i][1] - points.append((x, y)) - # Allocate space for final output - imgMorph = np . zeros(img1 . shape, dtype=img1 . dtype) - with open(r"C:\Users\Anustup\Desktop\Facemorph\tri.txt") as file: - for line in file: - x, y, z = line.split() - x = int(x) - y = int(y) - z = int(z) - t1 = [points1[x], points1[y], points1[z]] - t2 = [points2[x], points2[y], points2[z]] - t = [points[x], points[y], points[z]] - # Morph one triangle at a time. - morphTriangle(img1, img2, imgMorph, t1, t2, t, alpha) - cv2.imshow("Morphed Face", np.uint8(imgMorph)) - cv2.waitKey(0) +import numpy as np +import cv2 +# import sys +# Read points from text file + + +def readPoints(path): + # Create array of points + points = [] + # Read points + with open(path) as file: + for line in file: + x, y = line.split() + points.append((int(x), int(y))) + + return points + +# Apply affine transform calculated using srcTri and dstTri to src and +# output an image of size. + + +def applyAffineTransform(src, srcTri, dstTri, size): + # Given a pair of triangles, find the affine transform. + warpMat = cv2.getAffineTransform(np.float32(srcTri), np.float32(dstTri)) + # Apply the Affine Transform just found to the src image + dst = cv2.warpAffine(src, warpMat, (size[0], size[1]), None, + flags=cv2.INTER_LINEAR, + borderMode=cv2.BORDER_REFLECT_101) + return dst + + +# Warps and alpha blends triangular regions from img1 and img2 to img +def morphTriangle(img1, img2, img, t1, t2, t, alpha): + + # Find bounding rectangle for each triangle + r1 = cv2.boundingRect(np.float32([t1])) + r2 = cv2.boundingRect(np.float32([t2])) + r = cv2.boundingRect(np.float32([t])) + # Offset points by left top corner of the respective rectangles + t1Rect = [] + t2Rect = [] + tRect = [] + for i in range(0, 3): + tRect.append(((t[i][0] - r[0]), (t[i][1] - r[1]))) + t1Rect.append(((t1[i][0] - r1[0]), (t1[i][1] - r1[1]))) + t2Rect.append(((t2[i][0] - r2[0]), (t2[i][1] - r2[1]))) + mask = np . zeros((r[3], r[2], 3), dtype=np . float32) + cv2.fillConvexPoly(mask, np.int32(tRect), (1.0, 1.0, 1.0), 16, 0) + # Apply warpImage to small rectangular patches + img1Rect = img1[r1[1]:r1[1] + r1[3], r1[0]:r1[0] + r1[2]] + img2Rect = img2[r2[1]:r2[1] + r2[3], r2[0]:r2[0] + r2[2]] + size = (r[2], r[3]) + warpImage1 = applyAffineTransform(img1Rect, t1Rect, tRect, size) + warpImage2 = applyAffineTransform(img2Rect, t2Rect, tRect, size) + + # Alpha blend rectangular patches + imgRect = (1.0 - alpha) * warpImage1 + alpha * warpImage2 + + # Copy triangular region of the rectangular patch to the output image + img[r[1]: r[1] + r[3], r[0]: r[0] + r[2]] + img[r[1]: r[1] + r[3], r[0]: r[0] + r[2]] * (1 - mask) + imgRect * mask + + +if __name__ == '__main__': + filename1 = r"C:\Users\Anustup\Desktop\Facemorph\hilary_clinton.jpg" + filename2 = r"C:\Users\Anustup\Desktop\Facemorph\ted_cruz.jpg" + alpha = 0.5 + # Read images + img1 = cv2.imread(filename1) + img2 = cv2.imread(filename2) + # Convert Mat to float data type + img1 = np.float32(img1) + img2 = np.float32(img2) + # Read array of corresponding points + points1 = readPoints(filename1 + '.txt') + points2 = readPoints(filename2 + '.txt') + points = [] + # Compute weighted average point coordinates + for i in range(0, len(points1)): + x = (1 - alpha) * points1[i][0] + alpha * points2[i][0] + y = (1 - alpha) * points1[i][1] + alpha * points2[i][1] + points.append((x, y)) + # Allocate space for final output + imgMorph = np . zeros(img1 . shape, dtype=img1 . dtype) + with open(r"C:\Users\Anustup\Desktop\Facemorph\tri.txt") as file: + for line in file: + x, y, z = line.split() + x = int(x) + y = int(y) + z = int(z) + t1 = [points1[x], points1[y], points1[z]] + t2 = [points2[x], points2[y], points2[z]] + t = [points[x], points[y], points[z]] + # Morph one triangle at a time. + morphTriangle(img1, img2, imgMorph, t1, t2, t, alpha) + cv2.imshow("Morphed Face", np.uint8(imgMorph)) + cv2.waitKey(0) diff --git a/face_morpher/requirements.txt b/face_morpher/requirements.txt index 86b29f656..e616f84d0 100644 --- a/face_morpher/requirements.txt +++ b/face_morpher/requirements.txt @@ -1,3 +1,3 @@ -numpy >= 1.0.0 -sys= 2.1.4 -cv2= 4.4.0.44 +numpy >= 1.0.0 +sys= 2.1.4 +cv2= 4.4.0.44 diff --git a/facemask_detector/README.md b/facemask_detector/README.md index 44d269fa8..daa08627f 100644 --- a/facemask_detector/README.md +++ b/facemask_detector/README.md @@ -1,34 +1,34 @@ -# Face Mask Detection in PyTorch - -Author - [abhinand5](https://github.com/abhinand5) - -The scripts in this project contains all the necessary code to predict if a person is wearing face mask. Actually it can predict 3 things, - -1. Wearing Mask - green box -2. Incorrectly wearing Mask - orange box -3. No mask - red box - -**Note: Since the saved model ckpt file and the data are too big, I have uploaded the saved model in google drive and linked the data source and drive link below.** - -[Data Source](https://www.kaggle.com/andrewmvd/face-mask-detection/) - -[Link to Saved Model](https://drive.google.com/file/d/1wPjFnbMY0zahUTXY6qpFY-VFTrnW0bfl/view?usp=sharing) - -## Installing requirements -You can run the following command to install the requirements, - -`$ pip install -r requirements.txt` - -## Usage -To detect face masks from your custom images...you can execute this following command -It takes two arguments, first one is the path to the image you want to use to predict and secondly the file name to save the results in. - -`$ python detect_face_mask.py [PATH TO YOUR IMAGE] [FILE NAME FOR RESULT]` - -Example: - -`$ python detect_face_mask.py ./my_image.png my_result` - -There are a few results already saved in the results folder. - +# Face Mask Detection in PyTorch + +Author - [abhinand5](https://github.com/abhinand5) + +The scripts in this project contains all the necessary code to predict if a person is wearing face mask. Actually it can predict 3 things, + +1. Wearing Mask - green box +2. Incorrectly wearing Mask - orange box +3. No mask - red box + +**Note: Since the saved model ckpt file and the data are too big, I have uploaded the saved model in google drive and linked the data source and drive link below.** + +[Data Source](https://www.kaggle.com/andrewmvd/face-mask-detection/) + +[Link to Saved Model](https://drive.google.com/file/d/1wPjFnbMY0zahUTXY6qpFY-VFTrnW0bfl/view?usp=sharing) + +## Installing requirements +You can run the following command to install the requirements, + +`$ pip install -r requirements.txt` + +## Usage +To detect face masks from your custom images...you can execute this following command +It takes two arguments, first one is the path to the image you want to use to predict and secondly the file name to save the results in. + +`$ python detect_face_mask.py [PATH TO YOUR IMAGE] [FILE NAME FOR RESULT]` + +Example: + +`$ python detect_face_mask.py ./my_image.png my_result` + +There are a few results already saved in the results folder. + You can play with the code to do any sort of retraining of the model. \ No newline at end of file diff --git a/facemask_detector/dataset.py b/facemask_detector/dataset.py index 4f6bc77d8..0578d11df 100644 --- a/facemask_detector/dataset.py +++ b/facemask_detector/dataset.py @@ -1,81 +1,81 @@ -# Author - Abhinand --> https://github.com/abhinand5 -# ===================================================================== -# IMPORTS -# ====================================================================== - -import torch - -import os -from PIL import Image -from bs4 import BeautifulSoup - -###################################################################### -# Data source - https://www.kaggle.com/andrewmvd/face-mask-detection -# ===================================================================== -# Writing the Dataset class for PyTorch -# ====================================================================== - - -class FaceMaskDataset(object): - def __init__(self, transforms): - self.images = list(sorted(os.listdir("./data/images"))) - self.annotations = list(sorted(os.listdir("./data/annotations"))) - self.transforms = transforms - - def __len__(self): - return len(self.images) - - def __getitem__(self, idx): - img = "maksssksksss" + str(idx) + ".png" - label = "maksssksksss" + str(idx) + ".xml" - - img_path = os.path.join("./data/images/", img) - label_path = os.path.join("./data/annotations/", label) - - img = Image.open(img_path).convert("RGB") - label = self.generate_label(idx, label_path) - - if self.transforms is not None: - img = self.transforms(img) - - return img, label - - def generate_label(self, image_idx, label_file): - with open(label_file) as f: - data = f.read() - soup = BeautifulSoup(data, "xml") - objects = soup.find_all("object") - - boxes = [] - labels = [] - - for ob in objects: - boxes.append(self.get_box(ob)) - labels.append(self.get_label(ob)) - - boxes = torch.as_tensor(boxes, dtype=torch.float32) - labels = torch.as_tensor(labels, dtype=torch.int64) - - img_idx = torch.tensor([image_idx]) - - target = {} - target["boxes"] = boxes - target["labels"] = labels - target["image_id"] = img_idx - - return target - - def get_label(self, obj): - if obj.find("name").text == "with_mask": - return 1 - elif obj.find("name").text == "mask_weared_incorrect": - return 2 - return 3 - - def get_box(self, obj): - x0 = int(obj.find("xmin").text) - x1 = int(obj.find("xmax").text) - y0 = int(obj.find("ymin").text) - y1 = int(obj.find("ymax").text) - - return [x0, y0, x1, y1] +# Author - Abhinand --> https://github.com/abhinand5 +# ===================================================================== +# IMPORTS +# ====================================================================== + +import torch + +import os +from PIL import Image +from bs4 import BeautifulSoup + +###################################################################### +# Data source - https://www.kaggle.com/andrewmvd/face-mask-detection +# ===================================================================== +# Writing the Dataset class for PyTorch +# ====================================================================== + + +class FaceMaskDataset(object): + def __init__(self, transforms): + self.images = list(sorted(os.listdir("./data/images"))) + self.annotations = list(sorted(os.listdir("./data/annotations"))) + self.transforms = transforms + + def __len__(self): + return len(self.images) + + def __getitem__(self, idx): + img = "maksssksksss" + str(idx) + ".png" + label = "maksssksksss" + str(idx) + ".xml" + + img_path = os.path.join("./data/images/", img) + label_path = os.path.join("./data/annotations/", label) + + img = Image.open(img_path).convert("RGB") + label = self.generate_label(idx, label_path) + + if self.transforms is not None: + img = self.transforms(img) + + return img, label + + def generate_label(self, image_idx, label_file): + with open(label_file) as f: + data = f.read() + soup = BeautifulSoup(data, "xml") + objects = soup.find_all("object") + + boxes = [] + labels = [] + + for ob in objects: + boxes.append(self.get_box(ob)) + labels.append(self.get_label(ob)) + + boxes = torch.as_tensor(boxes, dtype=torch.float32) + labels = torch.as_tensor(labels, dtype=torch.int64) + + img_idx = torch.tensor([image_idx]) + + target = {} + target["boxes"] = boxes + target["labels"] = labels + target["image_id"] = img_idx + + return target + + def get_label(self, obj): + if obj.find("name").text == "with_mask": + return 1 + elif obj.find("name").text == "mask_weared_incorrect": + return 2 + return 3 + + def get_box(self, obj): + x0 = int(obj.find("xmin").text) + x1 = int(obj.find("xmax").text) + y0 = int(obj.find("ymin").text) + y1 = int(obj.find("ymax").text) + + return [x0, y0, x1, y1] diff --git a/facemask_detector/detect_face_mask.py b/facemask_detector/detect_face_mask.py index a9173b748..2ce0607c1 100644 --- a/facemask_detector/detect_face_mask.py +++ b/facemask_detector/detect_face_mask.py @@ -1,56 +1,56 @@ -# Author - Abhinand --> https://github.com/abhinand5 -# ===================================================================== -# IMPORTS -# ====================================================================== - -import torch -from torchvision import transforms - -import os -import sys -from PIL import Image - -from model import FaceMaskDetector -from train import plot_result - -# ===================================================================== -# HELPER FUNCTION TO PREDICT CUSTOM IMAGES AND SAVE IN RESULTS DIR -# ====================================================================== - - -def predict(img_path, model): - if os.path.splitext(img_path)[-1] not in [".jpg", ".png", ".jpeg"]: - raise Exception( - f"Image format ->{os.path.splitext(img_path)[-1]}<- not supported" - ) - - image = Image.open(img_path).convert("RGB") - to_tensor = transforms.ToTensor() - image_t = to_tensor(image) - - pred = model.predict(image_t.unsqueeze(0)) - - return image_t, pred - - -if __name__ == "__main__": - - device = torch.device("cpu") - print("Device set to: ", device) - - model = FaceMaskDetector(data_loader=None, device=device, pretrained=True) - - model.build_model(n_classes=3) - - LOAD_CKPT = "./faster-rcnn_s2.ckpt" - model.load_model(LOAD_CKPT) - - img_path = sys.argv[1] - save_name = sys.argv[2] - - print("Running image through the model...") - - image_t, pred = predict(img_path, model) - plot_result(image_t, pred[0], save_name) - - print(f"Successfully saved result image at ./results/{save_name}") +# Author - Abhinand --> https://github.com/abhinand5 +# ===================================================================== +# IMPORTS +# ====================================================================== + +import torch +from torchvision import transforms + +import os +import sys +from PIL import Image + +from model import FaceMaskDetector +from train import plot_result + +# ===================================================================== +# HELPER FUNCTION TO PREDICT CUSTOM IMAGES AND SAVE IN RESULTS DIR +# ====================================================================== + + +def predict(img_path, model): + if os.path.splitext(img_path)[-1] not in [".jpg", ".png", ".jpeg"]: + raise Exception( + f"Image format ->{os.path.splitext(img_path)[-1]}<- not supported" + ) + + image = Image.open(img_path).convert("RGB") + to_tensor = transforms.ToTensor() + image_t = to_tensor(image) + + pred = model.predict(image_t.unsqueeze(0)) + + return image_t, pred + + +if __name__ == "__main__": + + device = torch.device("cpu") + print("Device set to: ", device) + + model = FaceMaskDetector(data_loader=None, device=device, pretrained=True) + + model.build_model(n_classes=3) + + LOAD_CKPT = "./faster-rcnn_s2.ckpt" + model.load_model(LOAD_CKPT) + + img_path = sys.argv[1] + save_name = sys.argv[2] + + print("Running image through the model...") + + image_t, pred = predict(img_path, model) + plot_result(image_t, pred[0], save_name) + + print(f"Successfully saved result image at ./results/{save_name}") diff --git a/facemask_detector/model.py b/facemask_detector/model.py index b7d7a1d03..ba1b7c5e9 100644 --- a/facemask_detector/model.py +++ b/facemask_detector/model.py @@ -1,94 +1,94 @@ -# Author - Abhinand --> https://github.com/abhinand5 -# ===================================================================== -# IMPORTS -# ====================================================================== - -import torch -import torchvision -from torchvision.models.detection.faster_rcnn import FastRCNNPredictor - -import pkbar - -# ===================================================================== -# PyTorch class for the model -# ====================================================================== - - -class FaceMaskDetector(object): - def __init__(self, data_loader, device, pretrained=True): - self.pretrained = pretrained - self.data_loader = data_loader - self.device = device - - def build_model(self, n_classes): - model = torchvision.models.detection.fasterrcnn_resnet50_fpn( - pretrained=self.pretrained - ) - in_features = model.roi_heads.box_predictor.cls_score.in_features - model.roi_heads.box_predictor = FastRCNNPredictor( - in_features, - n_classes + 1 - ) - - self.model = model - - def train(self, n_epochs, learning_rate): - dl_len = len(self.data_loader) - - self.model.to(self.device) - params = [p for p in self.model.parameters() if p.requires_grad] - optimizer = torch.optim.SGD( - params, lr=learning_rate, momentum=0.9, weight_decay=0.0005 - ) - - losses_per_ep = [] - - for epoch in range(n_epochs): - self.model.train() - - ep_loss = 0 - kbar = pkbar.Kbar( - target=dl_len, - epoch=epoch, - num_epochs=n_epochs, - width=20, - always_stateful=True, - ) - - for i, (images, annotations) in enumerate(self.data_loader): - images = list(image.to(self.device) for image in images) - annotations = [ - { - k: v.to(self.device) - for k, v in t.items() - } for t in annotations - ] - - losses = self.model([images[0]], [annotations[0]]) - loss = sum(loss for loss in losses.values()) - - optimizer.zero_grad() - loss.backward() - optimizer.step() - - ep_loss += loss.item() - - kbar.update(i, values=[("loss", ep_loss)]) - - losses_per_ep.append(ep_loss) - kbar.add(1) - - return losses_per_ep - - def predict(self, images): - self.model.to(self.device) - self.model.eval() - preds = self.model(images) - - return preds - - def save_model(self, path): - torch.save(self.model.state_dict(), path) - - def load_model(self, path): - self.model.load_state_dict(torch.load(path)) +# Author - Abhinand --> https://github.com/abhinand5 +# ===================================================================== +# IMPORTS +# ====================================================================== + +import torch +import torchvision +from torchvision.models.detection.faster_rcnn import FastRCNNPredictor + +import pkbar + +# ===================================================================== +# PyTorch class for the model +# ====================================================================== + + +class FaceMaskDetector(object): + def __init__(self, data_loader, device, pretrained=True): + self.pretrained = pretrained + self.data_loader = data_loader + self.device = device + + def build_model(self, n_classes): + model = torchvision.models.detection.fasterrcnn_resnet50_fpn( + pretrained=self.pretrained + ) + in_features = model.roi_heads.box_predictor.cls_score.in_features + model.roi_heads.box_predictor = FastRCNNPredictor( + in_features, + n_classes + 1 + ) + + self.model = model + + def train(self, n_epochs, learning_rate): + dl_len = len(self.data_loader) + + self.model.to(self.device) + params = [p for p in self.model.parameters() if p.requires_grad] + optimizer = torch.optim.SGD( + params, lr=learning_rate, momentum=0.9, weight_decay=0.0005 + ) + + losses_per_ep = [] + + for epoch in range(n_epochs): + self.model.train() + + ep_loss = 0 + kbar = pkbar.Kbar( + target=dl_len, + epoch=epoch, + num_epochs=n_epochs, + width=20, + always_stateful=True, + ) + + for i, (images, annotations) in enumerate(self.data_loader): + images = list(image.to(self.device) for image in images) + annotations = [ + { + k: v.to(self.device) + for k, v in t.items() + } for t in annotations + ] + + losses = self.model([images[0]], [annotations[0]]) + loss = sum(loss for loss in losses.values()) + + optimizer.zero_grad() + loss.backward() + optimizer.step() + + ep_loss += loss.item() + + kbar.update(i, values=[("loss", ep_loss)]) + + losses_per_ep.append(ep_loss) + kbar.add(1) + + return losses_per_ep + + def predict(self, images): + self.model.to(self.device) + self.model.eval() + preds = self.model(images) + + return preds + + def save_model(self, path): + torch.save(self.model.state_dict(), path) + + def load_model(self, path): + self.model.load_state_dict(torch.load(path)) diff --git a/facemask_detector/requirements.txt b/facemask_detector/requirements.txt index 970095ce4..fd9ad0a94 100644 --- a/facemask_detector/requirements.txt +++ b/facemask_detector/requirements.txt @@ -1,6 +1,6 @@ -torchvision==0.7.0 -matplotlib==3.3.1 -pkbar==0.5 -torch==1.6.0 -beautifulsoup4==4.9.3 -Pillow==8.0.0 +torchvision==0.7.0 +matplotlib==3.3.1 +pkbar==0.5 +torch==1.6.0 +beautifulsoup4==4.9.3 +Pillow==8.0.0 diff --git a/facemask_detector/train.py b/facemask_detector/train.py index 610f95c9e..de9b7ccae 100644 --- a/facemask_detector/train.py +++ b/facemask_detector/train.py @@ -1,130 +1,130 @@ -# Author - Abhinand --> https://github.com/abhinand5 -# ===================================================================== -# IMPORTS -# ====================================================================== - -import torch -from torchvision import transforms - -import os - -from dataset import FaceMaskDataset -from model import FaceMaskDetector - -import matplotlib.pyplot as plt -import matplotlib.patches as patches - -import warnings - -warnings.filterwarnings("ignore") - - -def plot_result(image_tensor, annotations, savename, ucb=0.9): - """Helper function to plot and save the results""" - fig, ax = plt.subplots(1) - image = image_tensor.cpu().data - - ax.imshow(image.permute(1, 2, 0)) - - color_map = {1: "green", 2: "orange", 3: "red"} - - for i, box in enumerate(annotations["boxes"]): - if float(annotations["scores"][i]) > ucb: - x0, y0, x1, y1 = box - - color = color_map[int(annotations["labels"][i])] - rect = patches.Rectangle( - (x0, y0), - (x1 - x0), - (y1 - y0), - linewidth=1, - edgecolor=color, - facecolor="none", - ) - - ax.add_patch(rect) - else: - pass - - plt.axis("off") - plt.savefig(f"./results/{savename}.png") - - -# ====================================================================== -# Setting up Device and Data -# ====================================================================== -if __name__ == "__main__": - - # Set device - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - - print("Device set to: ", device) - - # Get images and annotations - images = list(sorted(os.listdir("./data/images"))) - annotations = list(sorted(os.listdir("./data/annotations"))) - - # Set up data for training - BATCH_SIZE = 4 - - data_transform = transforms.Compose( - [ - transforms.ToTensor(), - ] - ) - - def collate_fn(batch): - return tuple(zip(*batch)) - - # Create the torch dataset - dataset = FaceMaskDataset(transforms=data_transform) - data_loader = torch.utils.data.DataLoader( - dataset, batch_size=BATCH_SIZE, collate_fn=collate_fn - ) - - # ====================================================================== - # Training the Faster-RCNN model - # ====================================================================== - model = FaceMaskDetector( - data_loader=data_loader, - device=device, - pretrained=True - ) - - model.build_model(n_classes=3) - - LOAD = True - LOAD_CKPT = "./faster-rcnn_s2.ckpt" - SAVE_CKPT = "./faster-rcnn_s2.ckpt" - - N_EPOCHS = 10 - LEARNING_RATE = 0.005 - - if LOAD: - model.load_model(LOAD_CKPT) - - losses = model.train(n_epochs=N_EPOCHS, learning_rate=LEARNING_RATE) - model.save_model(SAVE_CKPT) - - # ====================================================================== - # Making inference using the trained model - # ====================================================================== - iters = 1 - ctr = 0 - - for i, (imgs, annotations) in enumerate(data_loader): - if i > iters - 1: - break - imgs = list(img.to(device) for img in imgs) - annotations = [ - {k: v.to(device) for k, v in t.items()} - for t in annotations - ] - - pred = model.predict(imgs) - - for j in range(len(pred)): - plot_result(imgs[j], pred[j], ucb=0.8, savename=ctr) - ctr += 1 - - print("Resultant images saved at './results/' folder") +# Author - Abhinand --> https://github.com/abhinand5 +# ===================================================================== +# IMPORTS +# ====================================================================== + +import torch +from torchvision import transforms + +import os + +from dataset import FaceMaskDataset +from model import FaceMaskDetector + +import matplotlib.pyplot as plt +import matplotlib.patches as patches + +import warnings + +warnings.filterwarnings("ignore") + + +def plot_result(image_tensor, annotations, savename, ucb=0.9): + """Helper function to plot and save the results""" + fig, ax = plt.subplots(1) + image = image_tensor.cpu().data + + ax.imshow(image.permute(1, 2, 0)) + + color_map = {1: "green", 2: "orange", 3: "red"} + + for i, box in enumerate(annotations["boxes"]): + if float(annotations["scores"][i]) > ucb: + x0, y0, x1, y1 = box + + color = color_map[int(annotations["labels"][i])] + rect = patches.Rectangle( + (x0, y0), + (x1 - x0), + (y1 - y0), + linewidth=1, + edgecolor=color, + facecolor="none", + ) + + ax.add_patch(rect) + else: + pass + + plt.axis("off") + plt.savefig(f"./results/{savename}.png") + + +# ====================================================================== +# Setting up Device and Data +# ====================================================================== +if __name__ == "__main__": + + # Set device + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + print("Device set to: ", device) + + # Get images and annotations + images = list(sorted(os.listdir("./data/images"))) + annotations = list(sorted(os.listdir("./data/annotations"))) + + # Set up data for training + BATCH_SIZE = 4 + + data_transform = transforms.Compose( + [ + transforms.ToTensor(), + ] + ) + + def collate_fn(batch): + return tuple(zip(*batch)) + + # Create the torch dataset + dataset = FaceMaskDataset(transforms=data_transform) + data_loader = torch.utils.data.DataLoader( + dataset, batch_size=BATCH_SIZE, collate_fn=collate_fn + ) + + # ====================================================================== + # Training the Faster-RCNN model + # ====================================================================== + model = FaceMaskDetector( + data_loader=data_loader, + device=device, + pretrained=True + ) + + model.build_model(n_classes=3) + + LOAD = True + LOAD_CKPT = "./faster-rcnn_s2.ckpt" + SAVE_CKPT = "./faster-rcnn_s2.ckpt" + + N_EPOCHS = 10 + LEARNING_RATE = 0.005 + + if LOAD: + model.load_model(LOAD_CKPT) + + losses = model.train(n_epochs=N_EPOCHS, learning_rate=LEARNING_RATE) + model.save_model(SAVE_CKPT) + + # ====================================================================== + # Making inference using the trained model + # ====================================================================== + iters = 1 + ctr = 0 + + for i, (imgs, annotations) in enumerate(data_loader): + if i > iters - 1: + break + imgs = list(img.to(device) for img in imgs) + annotations = [ + {k: v.to(device) for k, v in t.items()} + for t in annotations + ] + + pred = model.predict(imgs) + + for j in range(len(pred)): + plot_result(imgs[j], pred[j], ucb=0.8, savename=ctr) + ctr += 1 + + print("Resultant images saved at './results/' folder") diff --git a/file_arranger/README.md b/file_arranger/README.md index 31796fc2e..acfdc115c 100644 --- a/file_arranger/README.md +++ b/file_arranger/README.md @@ -1,9 +1,9 @@ -# File Arranger - -Put this python file into the folder you want to arrange and then execute. - -You can also execute it via terminal by passing the full path to this. - -```folder\you\want\to\execute>python path\to\file_arranger\file_arranger.py``` - -You may also just run the ```file_arraner.exe``` if you're on windows. +# File Arranger + +Put this python file into the folder you want to arrange and then execute. + +You can also execute it via terminal by passing the full path to this. + +```folder\you\want\to\execute>python path\to\file_arranger\file_arranger.py``` + +You may also just run the ```file_arraner.exe``` if you're on windows. diff --git a/file_arranger/file_arranger.py b/file_arranger/file_arranger.py index 71784caad..b227fda79 100644 --- a/file_arranger/file_arranger.py +++ b/file_arranger/file_arranger.py @@ -1,56 +1,56 @@ -import os -from pathlib import Path - - -def organize_junk(): - for entry in os.scandir(): - if entry.is_dir(): - continue - - file_path = Path(entry) - file_format = file_path.suffix.lower() - - if file_format in FILE_FORMATS: - directory_path = Path(FILE_FORMATS[file_format]) - directory_path.mkdir(exist_ok=True) - file_path.rename(directory_path.joinpath(file_path)) - - else: - directory_path = Path('Others') - directory_path.mkdir(exist_ok=True) - file_path.rename(directory_path.joinpath(file_path)) - - for dir in os.scandir(): - try: - os.rmdir(dir) - except Exception: - pass - - -DIRECTORIES = { - - "Webpages": [".html5", ".html", ".htm", ".xhtml", ".aspx", ".php"], - - "Images": [".jpg", ".jpeg", ".png", ".tiff", ".gif", ".bmp", ".bpg", ".svg", - ".heif", ".psd"], - - "Videos": [".avi", ".mp4", ".flv", ".mkv", ".wmv", ".mov", ".webm", ".vob", - ".3gp", ".mpeg", ".mpg", ".qt"], - - "Docs": [".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".epub", - ".opus", ".txt", ".in", ".out", ".xml"], - - "Archive": [".rar", ".zip", ".7z"], - - "Audio": [".mp3", ".aac", ".ogg", ".m4a", ".wav", ".aa", ".dvf", ".m4b", - ".m4p", ".msv", ".oga", ".raw", ".vox"] - -} - -FILE_FORMATS = {file_format: directory - for directory, file_formats in DIRECTORIES.items() - for file_format in file_formats} - - -if __name__ == "__main__": - organize_junk() +import os +from pathlib import Path + + +def organize_junk(): + for entry in os.scandir(): + if entry.is_dir(): + continue + + file_path = Path(entry) + file_format = file_path.suffix.lower() + + if file_format in FILE_FORMATS: + directory_path = Path(FILE_FORMATS[file_format]) + directory_path.mkdir(exist_ok=True) + file_path.rename(directory_path.joinpath(file_path)) + + else: + directory_path = Path('Others') + directory_path.mkdir(exist_ok=True) + file_path.rename(directory_path.joinpath(file_path)) + + for dir in os.scandir(): + try: + os.rmdir(dir) + except Exception: + pass + + +DIRECTORIES = { + + "Webpages": [".html5", ".html", ".htm", ".xhtml", ".aspx", ".php"], + + "Images": [".jpg", ".jpeg", ".png", ".tiff", ".gif", ".bmp", ".bpg", ".svg", + ".heif", ".psd"], + + "Videos": [".avi", ".mp4", ".flv", ".mkv", ".wmv", ".mov", ".webm", ".vob", + ".3gp", ".mpeg", ".mpg", ".qt"], + + "Docs": [".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".epub", + ".opus", ".txt", ".in", ".out", ".xml"], + + "Archive": [".rar", ".zip", ".7z"], + + "Audio": [".mp3", ".aac", ".ogg", ".m4a", ".wav", ".aa", ".dvf", ".m4b", + ".m4p", ".msv", ".oga", ".raw", ".vox"] + +} + +FILE_FORMATS = {file_format: directory + for directory, file_formats in DIRECTORIES.items() + for file_format in file_formats} + + +if __name__ == "__main__": + organize_junk() diff --git a/file_encrypter/README.md b/file_encrypter/README.md index c46a92d4f..a60a52722 100644 --- a/file_encrypter/README.md +++ b/file_encrypter/README.md @@ -1,63 +1,63 @@ -# Using file_encrypter and file_decrypter Script - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## Steps to encrypt the PDF file : - -1. run the script `file_encrypter.py` and pass the path of the file as an argument. -Example : - ``` - python file_encrypter.py ./test_file.pdf - ``` - -2. Enter the password when prompted. - - ___NOTE : The password should satisfy the following criteria :___ - - at least 8 characters in length - - at least one lowercase character - - at least one uppercase character - - at least one digit (0-9) - - at least one special character [@_!#$%^&*()<>?/\|}{~:] - - ___Otherwise the password will be classified as weak and you will be asked to enter a strong password as shown below___ - - Example : - ``` - password for encrypting : testpass - WEAK Password - Please enter a strong password - password for encrypting : Test@1234 - ``` - -3. You will get the following prompt with the relative path to the encrypted file. - ``` - FILE HAS BEEN ENCRYPTED SUCCESSFULLY. STORED IN ./test_file.pdf.aes - ``` - -## Steps to decrypt the encrypted PDF file : - -1. run the script `file_decrypter.py` and pass the path of the file as an argument. -Example : - ``` - python file_decrypter.py ./test_file.pdf.aes - ``` - -2. Enter the password when prompted. -Example : - ``` - password for encrypting : Test@1234 - ``` - -3. On __Successful decryption__ you will get the following prompt with the relative path to the decrypted file. - ``` - FILE HAS BEEN DECRYPTED SUCCESSFULLY. STORED IN ./test_file.pdf - ``` - On __Failure__ you will get the following prompt - ``` - WRONG PASSWORD OR THE FILE IS CORRUPTED - ``` +# Using file_encrypter and file_decrypter Script + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## Steps to encrypt the PDF file : + +1. run the script `file_encrypter.py` and pass the path of the file as an argument. +Example : + ``` + python file_encrypter.py ./test_file.pdf + ``` + +2. Enter the password when prompted. + + ___NOTE : The password should satisfy the following criteria :___ + - at least 8 characters in length + - at least one lowercase character + - at least one uppercase character + - at least one digit (0-9) + - at least one special character [@_!#$%^&*()<>?/\|}{~:] + + ___Otherwise the password will be classified as weak and you will be asked to enter a strong password as shown below___ + + Example : + ``` + password for encrypting : testpass + WEAK Password + Please enter a strong password + password for encrypting : Test@1234 + ``` + +3. You will get the following prompt with the relative path to the encrypted file. + ``` + FILE HAS BEEN ENCRYPTED SUCCESSFULLY. STORED IN ./test_file.pdf.aes + ``` + +## Steps to decrypt the encrypted PDF file : + +1. run the script `file_decrypter.py` and pass the path of the file as an argument. +Example : + ``` + python file_decrypter.py ./test_file.pdf.aes + ``` + +2. Enter the password when prompted. +Example : + ``` + password for encrypting : Test@1234 + ``` + +3. On __Successful decryption__ you will get the following prompt with the relative path to the decrypted file. + ``` + FILE HAS BEEN DECRYPTED SUCCESSFULLY. STORED IN ./test_file.pdf + ``` + On __Failure__ you will get the following prompt + ``` + WRONG PASSWORD OR THE FILE IS CORRUPTED + ``` diff --git a/file_encrypter/file_decrypter.py b/file_encrypter/file_decrypter.py index 2a9aa57e1..f944d41f9 100644 --- a/file_encrypter/file_decrypter.py +++ b/file_encrypter/file_decrypter.py @@ -1,10 +1,10 @@ -import pyAesCrypt -import sys -bufferSize = 64 * 1024 -password = input("password for decrypting : ") -opname = sys.argv[1].replace(".aes", "") -try: - pyAesCrypt.decryptFile(sys.argv[1], opname, password, bufferSize) - print(f"FILE HAS BEEN DECRYPTED SUCCESSFULLY. STORED IN {opname}") -except ValueError: - print("WRONG PASSWORD OR THE FILE IS CORRUPTED") +import pyAesCrypt +import sys +bufferSize = 64 * 1024 +password = input("password for decrypting : ") +opname = sys.argv[1].replace(".aes", "") +try: + pyAesCrypt.decryptFile(sys.argv[1], opname, password, bufferSize) + print(f"FILE HAS BEEN DECRYPTED SUCCESSFULLY. STORED IN {opname}") +except ValueError: + print("WRONG PASSWORD OR THE FILE IS CORRUPTED") diff --git a/file_encrypter/file_encrypter.py b/file_encrypter/file_encrypter.py index 3c7764aad..f255f3eee 100644 --- a/file_encrypter/file_encrypter.py +++ b/file_encrypter/file_encrypter.py @@ -1,36 +1,36 @@ -import pyAesCrypt -import sys -import re - -bufferSize = 64 * 1024 - - -def check_password(password): - """ - function to check the strength of password - """ - regex = re.compile('[@_!#$%^&*()<>?/\\|}{~:]') - - t1 = len(password) >= 8 - t2 = not (regex.search(password) is None) - t3 = any(c.islower() for c in password) - t4 = any(c.isupper() for c in password) - t5 = any(c.isdigit() for c in password) - - if t1 and t2 and t3 and t4 and t5: - return True - else: - return False - - -password = input("password for encrypting : ") -password_strength = check_password(password) - -while not password_strength: - print("WEAK Password") - print("Please enter a strong password") - password = input("password for encrypting : ") - password_strength = check_password(password) - -pyAesCrypt.encryptFile(sys.argv[1], f"{sys.argv[1]}.aes", password, bufferSize) -print(f"FILE HAS BEEN ENCRYPTED SUCCESSFULLY. STORED IN {sys.argv[1]}.aes") +import pyAesCrypt +import sys +import re + +bufferSize = 64 * 1024 + + +def check_password(password): + """ + function to check the strength of password + """ + regex = re.compile('[@_!#$%^&*()<>?/\\|}{~:]') + + t1 = len(password) >= 8 + t2 = not (regex.search(password) is None) + t3 = any(c.islower() for c in password) + t4 = any(c.isupper() for c in password) + t5 = any(c.isdigit() for c in password) + + if t1 and t2 and t3 and t4 and t5: + return True + else: + return False + + +password = input("password for encrypting : ") +password_strength = check_password(password) + +while not password_strength: + print("WEAK Password") + print("Please enter a strong password") + password = input("password for encrypting : ") + password_strength = check_password(password) + +pyAesCrypt.encryptFile(sys.argv[1], f"{sys.argv[1]}.aes", password, bufferSize) +print(f"FILE HAS BEEN ENCRYPTED SUCCESSFULLY. STORED IN {sys.argv[1]}.aes") diff --git a/file_encrypter/makefile b/file_encrypter/makefile index e78e53c81..7aafa604a 100644 --- a/file_encrypter/makefile +++ b/file_encrypter/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/file_mover/README.md b/file_mover/README.md index d769e5168..16fe14a27 100644 --- a/file_mover/README.md +++ b/file_mover/README.md @@ -1,10 +1,10 @@ -# filemover - -This script was written with python 3.9 - -To use this script you will just need to run it and follow the on screen instructions in the console. - -Basics of what will happen -- You will be asked "What directory would you like to move?". In which you will need to enter the FULL path to your desired folder. -- Next, you will be asked "Where would you like to transfer the contents?". Same as before, you will need to provide a full path to your desired folder, but if it does not exist the script will ask if you want it created. +# filemover + +This script was written with python 3.9 + +To use this script you will just need to run it and follow the on screen instructions in the console. + +Basics of what will happen +- You will be asked "What directory would you like to move?". In which you will need to enter the FULL path to your desired folder. +- Next, you will be asked "Where would you like to transfer the contents?". Same as before, you will need to provide a full path to your desired folder, but if it does not exist the script will ask if you want it created. - Once both directories are established, the code will run continuously (until exited) moving any files from the 1st folder to the 2nd provided. It will check every 30 seconds if there are any new files to move. Side Note: it will skip any folders it finds in the 1st folder provided. \ No newline at end of file diff --git a/file_mover/filemover.py b/file_mover/filemover.py index 93e555ad3..57688e379 100644 --- a/file_mover/filemover.py +++ b/file_mover/filemover.py @@ -1,56 +1,56 @@ -import os -import shutil -import time - -# 1st part asks the user what folder they want to pull files/data from -print('You are about to move files from one directory to another.') -dirA = input('What directory would you like to move? (please enter full path):') - -dirA_exist = os.path.exists(dirA) - -# checks if the folder exist or not -while os.path.exists(dirA) is not True: - dirA = input(f'{dirA} directory does not exist, please try again (please enter full path):') -else: - # 2nd part is to ask the user where they want to move the contents of a folder to - dirB = input(f'Where would you like to transfer the contents of {dirA}? (please enter full path):') - - # check's if the destination folder exist or not - while os.path.exists(dirB) is not True: - # asks the user if they would like to create the directory - Q1 = input(f'{dirB} does not exist, would you like to create it (Y/N)?') - - # if they say yes, it is create - if Q1 == 'Y': - print(f'Creating {dirB}') - os.mkdir(dirB) - print(f'{dirB} created') - - # if they say no, they are asked again where to transfer the files - elif Q1 == 'N': - dirB = input(f'Where would you like to transfer the contents of {dirA}? (please enter full path):') - - # if Y or N is not entered, user is asked to try again - else: - print('That is not a valid entry, please try again') - - # sets up a endless while loop to continuously move files from one to the other until the code is exited - running = True - while running: - - dir_contents = os.scandir(dirA) - - for content in dir_contents: - content_to_move = dirA + '\\' + content.name - # skips any folders found - if os.path.isdir(content_to_move): - print(f'{content_to_move} is a folder and not a file, skipping') - continue - # moves file one at a time - else: - shutil.move(dirA + '\\' + content.name, dirB) - print(f'File {content.name} has been moved') - - # sleeps for 30 seconds till it checks again - print('sleeping for 30 seconds') - time.sleep(30) +import os +import shutil +import time + +# 1st part asks the user what folder they want to pull files/data from +print('You are about to move files from one directory to another.') +dirA = input('What directory would you like to move? (please enter full path):') + +dirA_exist = os.path.exists(dirA) + +# checks if the folder exist or not +while os.path.exists(dirA) is not True: + dirA = input(f'{dirA} directory does not exist, please try again (please enter full path):') +else: + # 2nd part is to ask the user where they want to move the contents of a folder to + dirB = input(f'Where would you like to transfer the contents of {dirA}? (please enter full path):') + + # check's if the destination folder exist or not + while os.path.exists(dirB) is not True: + # asks the user if they would like to create the directory + Q1 = input(f'{dirB} does not exist, would you like to create it (Y/N)?') + + # if they say yes, it is create + if Q1 == 'Y': + print(f'Creating {dirB}') + os.mkdir(dirB) + print(f'{dirB} created') + + # if they say no, they are asked again where to transfer the files + elif Q1 == 'N': + dirB = input(f'Where would you like to transfer the contents of {dirA}? (please enter full path):') + + # if Y or N is not entered, user is asked to try again + else: + print('That is not a valid entry, please try again') + + # sets up a endless while loop to continuously move files from one to the other until the code is exited + running = True + while running: + + dir_contents = os.scandir(dirA) + + for content in dir_contents: + content_to_move = dirA + '\\' + content.name + # skips any folders found + if os.path.isdir(content_to_move): + print(f'{content_to_move} is a folder and not a file, skipping') + continue + # moves file one at a time + else: + shutil.move(dirA + '\\' + content.name, dirB) + print(f'File {content.name} has been moved') + + # sleeps for 30 seconds till it checks again + print('sleeping for 30 seconds') + time.sleep(30) diff --git a/fork_and_clone/Fnc.py b/fork_and_clone/Fnc.py index 106cfd31a..11704bfb9 100644 --- a/fork_and_clone/Fnc.py +++ b/fork_and_clone/Fnc.py @@ -1,65 +1,65 @@ -import subprocess -import sys -from github import Github - - -def fork(): - - print("To quit at any point click ctrl-c") - accOrOrg = input( - "Fork to your profile or an organization" - "(type org for organization, acc for profile): ") - while (accOrOrg != "acc" and accOrOrg != "org"): - accOrOrg = input("invalid answer: acc or org: ") - username = input("Your github username: ") - password = input("Your github password: ") - try: - g = Github(username, password) - user = g.get_user() - repo = input( - "Name of repo you want to fork (in the form owner/repo): ") - if (accOrOrg == "acc"): - user.create_fork(g.get_repo(repo)) - else: - org = input("name of your organization: ") - org = g.get_organization(org) - org.create_fork(g.get_repo(repo)) - clone(username, repo) - except Exception as e: - print("ERROR: " + str(e)) - print("You can try again or click ctrl-c and exit") - fork() - - -def clone(repo): - - location = input( - "Path for cloning repo into" - "(default is current directory): ") - try: - if len(location.strip()) != 0: - arr = repo.split("/") - subprocess.run( - "git clone https://github.com/" + repo + ".git " + location - + "\\" + arr[0] + "\\" + arr[1], shell=True, check=True) - else: - subprocess.run( - "git clone https://github.com/" + repo + ".git", - shell=True, check=True) - - except Exception as e: - print("ERROR: " + str(e)) - fnc = input( - "To start from the forking type fork, to start from" - "cloning type clone, to exit press ctrl-c: ").lower() - if fnc == "fork": - fork() - elif fnc == "clone": - clone(repo) - else: - print("Invalid Input: Exiting Now") - sys.exit() - - -if __name__ == "__main__": - fork() +import subprocess +import sys +from github import Github + + +def fork(): + + print("To quit at any point click ctrl-c") + accOrOrg = input( + "Fork to your profile or an organization" + "(type org for organization, acc for profile): ") + while (accOrOrg != "acc" and accOrOrg != "org"): + accOrOrg = input("invalid answer: acc or org: ") + username = input("Your github username: ") + password = input("Your github password: ") + try: + g = Github(username, password) + user = g.get_user() + repo = input( + "Name of repo you want to fork (in the form owner/repo): ") + if (accOrOrg == "acc"): + user.create_fork(g.get_repo(repo)) + else: + org = input("name of your organization: ") + org = g.get_organization(org) + org.create_fork(g.get_repo(repo)) + clone(username, repo) + except Exception as e: + print("ERROR: " + str(e)) + print("You can try again or click ctrl-c and exit") + fork() + + +def clone(repo): + + location = input( + "Path for cloning repo into" + "(default is current directory): ") + try: + if len(location.strip()) != 0: + arr = repo.split("/") + subprocess.run( + "git clone https://github.com/" + repo + ".git " + location + + "\\" + arr[0] + "\\" + arr[1], shell=True, check=True) + else: + subprocess.run( + "git clone https://github.com/" + repo + ".git", + shell=True, check=True) + + except Exception as e: + print("ERROR: " + str(e)) + fnc = input( + "To start from the forking type fork, to start from" + "cloning type clone, to exit press ctrl-c: ").lower() + if fnc == "fork": + fork() + elif fnc == "clone": + clone(repo) + else: + print("Invalid Input: Exiting Now") + sys.exit() + + +if __name__ == "__main__": + fork() diff --git a/fork_and_clone/README.md b/fork_and_clone/README.md index e05d0dba9..10c63add0 100644 --- a/fork_and_clone/README.md +++ b/fork_and_clone/README.md @@ -1,14 +1,14 @@ -# Fork and Clone a Repository - -A python script that forks and clones a repository. - - - You can fork into your own account or an organizations account. - - You can choose a path to clone the repository into (default is the repository of the script) - - You need to install the PyGithub wrapper library for the Github API. you need to have Git installed in your system so you can git clone, and you need Python 3.0 and above - - To get PyGithub, simply pip install pygithub - - To install Git please visit https://git-scm.com/downloads - -Usage: - - - Type into the command line Python (or Python3 if you have multple versions of python) Fnc.py and the script will prompt you for instructions - - Example: Python Fnc.py +# Fork and Clone a Repository + +A python script that forks and clones a repository. + + - You can fork into your own account or an organizations account. + - You can choose a path to clone the repository into (default is the repository of the script) + - You need to install the PyGithub wrapper library for the Github API. you need to have Git installed in your system so you can git clone, and you need Python 3.0 and above + - To get PyGithub, simply pip install pygithub + - To install Git please visit https://git-scm.com/downloads + +Usage: + + - Type into the command line Python (or Python3 if you have multple versions of python) Fnc.py and the script will prompt you for instructions + - Example: Python Fnc.py diff --git a/fork_and_clone/requirements.txt b/fork_and_clone/requirements.txt index cdeed1b1c..d26923921 100644 --- a/fork_and_clone/requirements.txt +++ b/fork_and_clone/requirements.txt @@ -1,2 +1,2 @@ -git = 2.20.0 -PyGithub = 1.5.3 +git = 2.20.0 +PyGithub = 1.5.3 diff --git a/github_scraper/README.md b/github_scraper/README.md index c7fa08f95..e99890238 100644 --- a/github_scraper/README.md +++ b/github_scraper/README.md @@ -1,26 +1,26 @@ -# Github users scrapper - -```bash -usage: scrapper.py [-h] [--json] user - -Fetch information about Github user. - -positional arguments: - user User that you want to look up into. - -optional arguments: - -h, --help show this help message and exit - --json Output data in json format -``` - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## Example usage -```bash -$ python3 scrapper.py python-geeks +# Github users scrapper + +```bash +usage: scrapper.py [-h] [--json] user + +Fetch information about Github user. + +positional arguments: + user User that you want to look up into. + +optional arguments: + -h, --help show this help message and exit + --json Output data in json format +``` + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## Example usage +```bash +$ python3 scrapper.py python-geeks ``` \ No newline at end of file diff --git a/github_scraper/makefile b/github_scraper/makefile index e78e53c81..7aafa604a 100644 --- a/github_scraper/makefile +++ b/github_scraper/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/github_scraper/requirements.txt b/github_scraper/requirements.txt index 989b995c6..927257d51 100644 --- a/github_scraper/requirements.txt +++ b/github_scraper/requirements.txt @@ -1 +1 @@ -requests==2.24.0 +requests==2.24.0 diff --git a/github_scraper/scrapper.py b/github_scraper/scrapper.py index 11405714f..fe99eed22 100644 --- a/github_scraper/scrapper.py +++ b/github_scraper/scrapper.py @@ -1,21 +1,21 @@ -import requests -import argparse - -parser = argparse.ArgumentParser(description='Fetch information about Github user.') -parser.add_argument('user', type=str, nargs=1, help='User that you want to look up into.') -parser.add_argument('--json', action='store_true', help='Output data in json format') - -args = vars(parser.parse_args()) -user = args["user"][0] -is_json = args["json"] - -API_URL = "https://api.github.com" - -req = requests.get(f'{API_URL}/users/{user}') -data = req.json() - -if is_json: - print(data) -else: - for key, value in data.items(): - print(f'{key}: {value}') +import requests +import argparse + +parser = argparse.ArgumentParser(description='Fetch information about Github user.') +parser.add_argument('user', type=str, nargs=1, help='User that you want to look up into.') +parser.add_argument('--json', action='store_true', help='Output data in json format') + +args = vars(parser.parse_args()) +user = args["user"][0] +is_json = args["json"] + +API_URL = "https://api.github.com" + +req = requests.get(f'{API_URL}/users/{user}') +data = req.json() + +if is_json: + print(data) +else: + for key, value in data.items(): + print(f'{key}: {value}') diff --git a/gmeet_joiner/README.md b/gmeet_joiner/README.md index 4f83b30cd..ccf5ac401 100644 --- a/gmeet_joiner/README.md +++ b/gmeet_joiner/README.md @@ -1,27 +1,27 @@ -# Google Meet Automation - -This python script will help you to join daily repetitve classses easily. - - -### Getting Started - -- Firstly clone the project to the desired location, and locate it in the terminal. You would have to download the required modules, you can do this by doing: - `pip install -r requirements.txt` or `pip3 install -r requirements.txt` - -- You can now modify the script slightly according to your schedule: - 1) If you are using chrome as you browser please replace the `for i in range(4)` at line 21 to: - `for i in range(5)` - - If you are using safari do not change the script. - - 2) You can now replace the links with your meet links at line 6 and 7. - - 3) You can replace the timings at line 47 and 48 (in military time): - - 4) Lastly you can replace 'command' with 'ctrl' if you are on windows. - -- This script will let you run two meetings that you have on a daily bases. - - -- Please note: The following program supports python3 - +# Google Meet Automation + +This python script will help you to join daily repetitve classses easily. + + +### Getting Started + +- Firstly clone the project to the desired location, and locate it in the terminal. You would have to download the required modules, you can do this by doing: + `pip install -r requirements.txt` or `pip3 install -r requirements.txt` + +- You can now modify the script slightly according to your schedule: + 1) If you are using chrome as you browser please replace the `for i in range(4)` at line 21 to: + `for i in range(5)` + + If you are using safari do not change the script. + + 2) You can now replace the links with your meet links at line 6 and 7. + + 3) You can replace the timings at line 47 and 48 (in military time): + + 4) Lastly you can replace 'command' with 'ctrl' if you are on windows. + +- This script will let you run two meetings that you have on a daily bases. + + +- Please note: The following program supports python3 + diff --git a/gmeet_joiner/main.py b/gmeet_joiner/main.py index fced7f22b..c693d2e0e 100644 --- a/gmeet_joiner/main.py +++ b/gmeet_joiner/main.py @@ -1,35 +1,35 @@ -import time -import webbrowser -import schedule -import pyautogui - - -url1 = "https://meet.google.com" -url2 = "https://www.google.com" - - -def attend_class(url): - webbrowser.open(url1) - time.sleep(3) - print("Joining Class") - time.sleep(2) - pyautogui.hotkey('command', 'd') - print("Turned off camera") - pyautogui.hotkey('command', 'e') - print("Turned off mic") - time.sleep(3) - - for i in range(4): - pyautogui.press('tab') - - time.sleep(3) - pyautogui.press('enter') - - -if __name__ == "__main__": - schedule.every().day.at("16:00").do(attend_class(url1)) - schedule.every().day.at("06:00").do(attend_class(url2)) - - while True: - schedule.run_pending() # check if we need to run anything - time.sleep(10) # wait 10 second before checking again +import time +import webbrowser +import schedule +import pyautogui + + +url1 = "https://meet.google.com" +url2 = "https://www.google.com" + + +def attend_class(url): + webbrowser.open(url1) + time.sleep(3) + print("Joining Class") + time.sleep(2) + pyautogui.hotkey('command', 'd') + print("Turned off camera") + pyautogui.hotkey('command', 'e') + print("Turned off mic") + time.sleep(3) + + for i in range(4): + pyautogui.press('tab') + + time.sleep(3) + pyautogui.press('enter') + + +if __name__ == "__main__": + schedule.every().day.at("16:00").do(attend_class(url1)) + schedule.every().day.at("06:00").do(attend_class(url2)) + + while True: + schedule.run_pending() # check if we need to run anything + time.sleep(10) # wait 10 second before checking again diff --git a/gmeet_joiner/requirements.txt b/gmeet_joiner/requirements.txt index d8a28a739..24b872a5a 100644 --- a/gmeet_joiner/requirements.txt +++ b/gmeet_joiner/requirements.txt @@ -1,4 +1,4 @@ -PyAutoGUI==0.9.52 -schedule==0.6.0 - - +PyAutoGUI==0.9.52 +schedule==0.6.0 + + diff --git a/google_images_scraper/README.md b/google_images_scraper/README.md index f412b084b..d9558caa6 100644 --- a/google_images_scraper/README.md +++ b/google_images_scraper/README.md @@ -1,11 +1,11 @@ -# Google Images Scraper -Python automation script to search and download images from google images. Takes cli arguments, can download about 250-300 images(beyond that the results get a bit diluted). - -Works on linux machines, this script has not been tested on windows or WSL(Windows Subsystem for Linux). - -## Installation - > pip3 install -r requirements.txt - -## Useage - > python3 google_images_scraper.py -s or --search "%SearchTerm" -d or --directory "%/Path/To/Download" -iC or --image_count "%NumberOfImagesToDownload" - +# Google Images Scraper +Python automation script to search and download images from google images. Takes cli arguments, can download about 250-300 images(beyond that the results get a bit diluted). + +Works on linux machines, this script has not been tested on windows or WSL(Windows Subsystem for Linux). + +## Installation + > pip3 install -r requirements.txt + +## Useage + > python3 google_images_scraper.py -s or --search "%SearchTerm" -d or --directory "%/Path/To/Download" -iC or --image_count "%NumberOfImagesToDownload" + diff --git a/google_images_scraper/google_images_scraper.py b/google_images_scraper/google_images_scraper.py index 66f38097d..6f3c20492 100644 --- a/google_images_scraper/google_images_scraper.py +++ b/google_images_scraper/google_images_scraper.py @@ -1,87 +1,87 @@ -from selenium import webdriver -from bs4 import BeautifulSoup -import urllib.request -import time -import argparse -import os - -import geckodriver_autoinstaller - - -def driver_download(): - # Check if the current version of geckodriver exists - # if it doesn't exist, download it automatically, - # then add geckodriver to PATH. - geckodriver_autoinstaller.install() - - -def google_images_scraper(): - GECKO_PATH = "/path/to/gecko/dir" # /usr/bin/geckodriver - if os.path.isfile(GECKO_PATH): - pass - else: - driver_download() - # taking user arguments - parser = argparse.ArgumentParser(description="Scrape Google images") - parser.add_argument( - "-s", "--search", default="mangoes", type=str, help="search term" - ) - parser.add_argument( - "-d", "--directory", default="images/", type=str, help="save directory" - ) - args = parser.parse_args() - query = args.search - savePath = args.directory - print("Search Term is " + query) - print("Images will be saved to " + savePath + " directory") - site = "https://www.google.com/search?tbm=isch&q=" + query - # providing driver path - driver = webdriver.Firefox(executable_path=GECKO_PATH) - # passing site url - driver.get(site) - """ - if you just want to download 10-15 images then skip the while loop and - just write - driver.execute_script("window.scrollBy(0,document.body.scrollHeight)") - below while loop scrolls the webpage 5 times(if available, - also scrolling beyond that the results get a bit diluted) - (will be able to retrieve around 250-300 images) - """ - i = 0 - while i < 5: - # for scrolling page - driver.execute_script("window.scrollBy(0,document.body.scrollHeight)") - - try: - # for clicking show more results button - driver.find_element_by_xpath( - "/html/body/div[2]/c-wiz/div[3]/div[1]/div/div/div/div/div[5]/input" - ).click() - - except Exception: - pass - time.sleep(5) - i += 1 - - # parsing - soup = BeautifulSoup(driver.page_source, "html.parser") - # closing web browser - driver.close() - # scraping image urls with the help of image tag and class used for images - imgTags = soup.find_all("img", class_="rg_i") - count = 0 - for i in imgTags: - - try: - # passing image urls one by one and downloading - urllib.request.urlretrieve(i["src"], savePath + str(count) + ".jpg") - count += 1 - print("Number of images downloaded = " + str(count), end="\r") - - except Exception: - pass - print("Total images downloaded = " + str(count)) - - -if __name__ == "__main__": - google_images_scraper() +from selenium import webdriver +from bs4 import BeautifulSoup +import urllib.request +import time +import argparse +import os + +import geckodriver_autoinstaller + + +def driver_download(): + # Check if the current version of geckodriver exists + # if it doesn't exist, download it automatically, + # then add geckodriver to PATH. + geckodriver_autoinstaller.install() + + +def google_images_scraper(): + GECKO_PATH = "/path/to/gecko/dir" # /usr/bin/geckodriver + if os.path.isfile(GECKO_PATH): + pass + else: + driver_download() + # taking user arguments + parser = argparse.ArgumentParser(description="Scrape Google images") + parser.add_argument( + "-s", "--search", default="mangoes", type=str, help="search term" + ) + parser.add_argument( + "-d", "--directory", default="images/", type=str, help="save directory" + ) + args = parser.parse_args() + query = args.search + savePath = args.directory + print("Search Term is " + query) + print("Images will be saved to " + savePath + " directory") + site = "https://www.google.com/search?tbm=isch&q=" + query + # providing driver path + driver = webdriver.Firefox(executable_path=GECKO_PATH) + # passing site url + driver.get(site) + """ + if you just want to download 10-15 images then skip the while loop and + just write + driver.execute_script("window.scrollBy(0,document.body.scrollHeight)") + below while loop scrolls the webpage 5 times(if available, + also scrolling beyond that the results get a bit diluted) + (will be able to retrieve around 250-300 images) + """ + i = 0 + while i < 5: + # for scrolling page + driver.execute_script("window.scrollBy(0,document.body.scrollHeight)") + + try: + # for clicking show more results button + driver.find_element_by_xpath( + "/html/body/div[2]/c-wiz/div[3]/div[1]/div/div/div/div/div[5]/input" + ).click() + + except Exception: + pass + time.sleep(5) + i += 1 + + # parsing + soup = BeautifulSoup(driver.page_source, "html.parser") + # closing web browser + driver.close() + # scraping image urls with the help of image tag and class used for images + imgTags = soup.find_all("img", class_="rg_i") + count = 0 + for i in imgTags: + + try: + # passing image urls one by one and downloading + urllib.request.urlretrieve(i["src"], savePath + str(count) + ".jpg") + count += 1 + print("Number of images downloaded = " + str(count), end="\r") + + except Exception: + pass + print("Total images downloaded = " + str(count)) + + +if __name__ == "__main__": + google_images_scraper() diff --git a/google_images_scraper/requirements.txt b/google_images_scraper/requirements.txt index de73b9c7f..b74b1825a 100644 --- a/google_images_scraper/requirements.txt +++ b/google_images_scraper/requirements.txt @@ -1,3 +1,3 @@ -selenium==3.141.0 -geckodriver_autoinstaller==0.1.0 -beautifulsoup4==4.9.3 +selenium==3.141.0 +geckodriver_autoinstaller==0.1.0 +beautifulsoup4==4.9.3 diff --git a/html_to_pdf/README.md b/html_to_pdf/README.md index d7ec9caa1..cde5c3c24 100644 --- a/html_to_pdf/README.md +++ b/html_to_pdf/README.md @@ -1,6 +1,6 @@ -1.Install Python3 on your system. -2.Install pip. -3.Setup virtual environment: make init (for Unix) -4.Install wkhtmltopdf ---> https://wkhtmltopdf.org/downloads.html depedning on your operating system. - +1.Install Python3 on your system. +2.Install pip. +3.Setup virtual environment: make init (for Unix) +4.Install wkhtmltopdf ---> https://wkhtmltopdf.org/downloads.html depedning on your operating system. + On setting up the above run the code as : python3 htmltopdf.py, it will prompt for the URL and the pdf output file. The converted file will be stored in the HTML_TO_PDF_Convertor. \ No newline at end of file diff --git a/html_to_pdf/htmtopdf.py b/html_to_pdf/htmtopdf.py index c42b66e6d..ff54ce5d4 100644 --- a/html_to_pdf/htmtopdf.py +++ b/html_to_pdf/htmtopdf.py @@ -1,5 +1,5 @@ -import pdfkit - -fr_url = input('Enter the url the html of which will be converted to pdf : ') -to_pdf = input('Enter the output of the file without pdf extension :') -pdfkit.from_url(fr_url, to_pdf + '.pdf') +import pdfkit + +fr_url = input('Enter the url the html of which will be converted to pdf : ') +to_pdf = input('Enter the output of the file without pdf extension :') +pdfkit.from_url(fr_url, to_pdf + '.pdf') diff --git a/html_to_pdf/makefile b/html_to_pdf/makefile index e78e53c81..7aafa604a 100644 --- a/html_to_pdf/makefile +++ b/html_to_pdf/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/html_to_pdf/requirements.txt b/html_to_pdf/requirements.txt index da9d589d7..697b19aa7 100644 --- a/html_to_pdf/requirements.txt +++ b/html_to_pdf/requirements.txt @@ -1 +1 @@ -pdfkit==0.6.1 +pdfkit==0.6.1 diff --git a/image_annotater/README.md b/image_annotater/README.md index de5f47d2f..cfba39fce 100644 --- a/image_annotater/README.md +++ b/image_annotater/README.md @@ -1,18 +1,18 @@ -# About the script : - -This Python script use Open CV to do annotation of images . The following script is deployed in a CV2 GUI visual format for better script value. The annotation is done by using CV2 , The following contains a visual out put of the script . - -## How to Run : -``` -pip install open-cv -python install requirements.txt -python run imageannotater.py -``` -A visual output screen will be visible where we can upload any image and do the annotation. - -### Input -![Alt_text](https://github.com/Anustup900/Automation-scripts/blob/main/ImageAnnotater/Assets/cat_dog.jpg) - -## Output : - -![Alt_text](https://github.com/Anustup900/Automation-scripts/blob/main/ImageAnnotater/Assets/cat_dog_annotated.jpg) +# About the script : + +This Python script use Open CV to do annotation of images . The following script is deployed in a CV2 GUI visual format for better script value. The annotation is done by using CV2 , The following contains a visual out put of the script . + +## How to Run : +``` +pip install open-cv +python install requirements.txt +python run imageannotater.py +``` +A visual output screen will be visible where we can upload any image and do the annotation. + +### Input +![Alt_text](https://github.com/Anustup900/Automation-scripts/blob/main/ImageAnnotater/Assets/cat_dog.jpg) + +## Output : + +![Alt_text](https://github.com/Anustup900/Automation-scripts/blob/main/ImageAnnotater/Assets/cat_dog_annotated.jpg) diff --git a/image_annotater/imageannotater.py b/image_annotater/imageannotater.py index 4b3f5d687..b308fe108 100644 --- a/image_annotater/imageannotater.py +++ b/image_annotater/imageannotater.py @@ -1,99 +1,99 @@ -import cv2 -import numpy as np -import pandas as pd -import sys -# Define the file name of the image -INPUT_IMAGE = sys.argv[1] -IMAGE_NAME = INPUT_IMAGE[:INPUT_IMAGE.index(".")] -OUTPUT_IMAGE = IMAGE_NAME + "_annotated.jpg" -output_csv_file = sys.argv[2] -# Load the image and store into a variable -# -1 means load unchanged -image = cv2.imread(INPUT_IMAGE, -1) -# Create lists to store all x, y, and annotation values -x_vals = [] -y_vals = [] -annotation_vals = [] -# Dictionary containing some colors -colors = {'blue': (255, 0, 0), 'green': (0, 255, 0), 'red': (0, 0, 255), - 'yellow': (0, 255, 255), 'magenta': (255, 0, 255), - 'cyan': (255, 255, 0), 'white': (255, 255, 255), 'black': (0, 0, 0), - 'gray': (125, 125, 125), - 'rand': np.random.randint(0, high=256, size=(3,)).tolist(), - 'dark_gray': (50, 50, 50), 'light_gray': (220, 220, 220)} - - -def draw_circle(event, x, y, flags, param): - """ - Draws dots on double clicking of the left mouse button - """ - # Store the height and width of the image - # height = image.shape[0] - width = image.shape[1] - - if event == cv2.EVENT_LBUTTONDBLCLK: - # Draw the dot - cv2.circle(image, (x, y), 5, colors['magenta'], -1) - - # Annotate the image - txt = input("Describe this pixel using one word (e.g. dog) and press ENTER: ") - - # Append values to the list - x_vals.append(x) - y_vals.append(y) - annotation_vals.append(txt) - - # Print the coordinates and the annotation to the console - print("x = " + str(x) + " y = " + str(y) - + " Annotation = " + txt + "\n") - - # Set the position of the text part of the annotation - text_x_pos = None - text_y_pos = y - - if x < (width / 2) : - text_x_pos = int(x + (width * 0.075)) - else: - text_x_pos = int(x - (width * 0.075)) - - # Write text on the image - cv2.putText(image, txt, (text_x_pos, text_y_pos), - cv2.FONT_HERSHEY_SIMPLEX, 1, colors['magenta'], 2) - - cv2.imwrite(OUTPUT_IMAGE, image) - - # Prompt user for another annotation - print("Double click another pixel or press 'q' to quit...\n") - - -print("Welcome to the Image Annotation Program!\n") -print("Double click anywhere inside the image to annotate that point...\n") - -# We create a named window where the mouse callback will be established -cv2.namedWindow('Image mouse') - -# We set the mouse callback function to 'draw_circle': -cv2.setMouseCallback('Image mouse', draw_circle) - -while True: - # Show image 'Image mouse': - cv2.imshow('Image mouse', image) - - # Continue until 'q' is pressed: - if cv2.waitKey(20) & 0xFF == ord('q'): - break - -# Create a dictionary using lists -data = {'X': x_vals, 'Y': y_vals, 'Annotation': annotation_vals} - -# Create the Pandas DataFrame -df = pd.DataFrame(data) -print() -print(df) -print() - -# Export the dataframe to a csv file -df.to_csv(path_or_buf=output_csv_file, index=None, header=True) - -# Destroy all generated windows: -cv2.destroyAllWindows() +import cv2 +import numpy as np +import pandas as pd +import sys +# Define the file name of the image +INPUT_IMAGE = sys.argv[1] +IMAGE_NAME = INPUT_IMAGE[:INPUT_IMAGE.index(".")] +OUTPUT_IMAGE = IMAGE_NAME + "_annotated.jpg" +output_csv_file = sys.argv[2] +# Load the image and store into a variable +# -1 means load unchanged +image = cv2.imread(INPUT_IMAGE, -1) +# Create lists to store all x, y, and annotation values +x_vals = [] +y_vals = [] +annotation_vals = [] +# Dictionary containing some colors +colors = {'blue': (255, 0, 0), 'green': (0, 255, 0), 'red': (0, 0, 255), + 'yellow': (0, 255, 255), 'magenta': (255, 0, 255), + 'cyan': (255, 255, 0), 'white': (255, 255, 255), 'black': (0, 0, 0), + 'gray': (125, 125, 125), + 'rand': np.random.randint(0, high=256, size=(3,)).tolist(), + 'dark_gray': (50, 50, 50), 'light_gray': (220, 220, 220)} + + +def draw_circle(event, x, y, flags, param): + """ + Draws dots on double clicking of the left mouse button + """ + # Store the height and width of the image + # height = image.shape[0] + width = image.shape[1] + + if event == cv2.EVENT_LBUTTONDBLCLK: + # Draw the dot + cv2.circle(image, (x, y), 5, colors['magenta'], -1) + + # Annotate the image + txt = input("Describe this pixel using one word (e.g. dog) and press ENTER: ") + + # Append values to the list + x_vals.append(x) + y_vals.append(y) + annotation_vals.append(txt) + + # Print the coordinates and the annotation to the console + print("x = " + str(x) + " y = " + str(y) + + " Annotation = " + txt + "\n") + + # Set the position of the text part of the annotation + text_x_pos = None + text_y_pos = y + + if x < (width / 2) : + text_x_pos = int(x + (width * 0.075)) + else: + text_x_pos = int(x - (width * 0.075)) + + # Write text on the image + cv2.putText(image, txt, (text_x_pos, text_y_pos), + cv2.FONT_HERSHEY_SIMPLEX, 1, colors['magenta'], 2) + + cv2.imwrite(OUTPUT_IMAGE, image) + + # Prompt user for another annotation + print("Double click another pixel or press 'q' to quit...\n") + + +print("Welcome to the Image Annotation Program!\n") +print("Double click anywhere inside the image to annotate that point...\n") + +# We create a named window where the mouse callback will be established +cv2.namedWindow('Image mouse') + +# We set the mouse callback function to 'draw_circle': +cv2.setMouseCallback('Image mouse', draw_circle) + +while True: + # Show image 'Image mouse': + cv2.imshow('Image mouse', image) + + # Continue until 'q' is pressed: + if cv2.waitKey(20) & 0xFF == ord('q'): + break + +# Create a dictionary using lists +data = {'X': x_vals, 'Y': y_vals, 'Annotation': annotation_vals} + +# Create the Pandas DataFrame +df = pd.DataFrame(data) +print() +print(df) +print() + +# Export the dataframe to a csv file +df.to_csv(path_or_buf=output_csv_file, index=None, header=True) + +# Destroy all generated windows: +cv2.destroyAllWindows() diff --git a/image_annotater/requirements.txt b/image_annotater/requirements.txt index 90da9773d..154fdc5c3 100644 --- a/image_annotater/requirements.txt +++ b/image_annotater/requirements.txt @@ -1,4 +1,4 @@ -pandas==1.1.3 -matplotlib==2.0.0 -numpy==1.12.0 -cv2 == 4.4.0.44 +pandas==1.1.3 +matplotlib==2.0.0 +numpy==1.12.0 +cv2 == 4.4.0.44 diff --git a/image_cartoonizer/README.md b/image_cartoonizer/README.md index bf1294bd0..e9a407ffe 100644 --- a/image_cartoonizer/README.md +++ b/image_cartoonizer/README.md @@ -1,11 +1,11 @@ -# Image Cartoonizer - Script to convert Image to cartoon - -This python script exatrcts cartton format of any input image by the help of RGB analysis in Open Cv , using py package CV2 .The following points contains description of how to use the script - -### How to Use the script : -``` -Step 1 : First clone the repo -Step 2 : Then install dependencies by python run requirements.txt -step 3 : Input an image to the script -Step 4 : Run the script and see the output -``` +# Image Cartoonizer - Script to convert Image to cartoon + +This python script exatrcts cartton format of any input image by the help of RGB analysis in Open Cv , using py package CV2 .The following points contains description of how to use the script + +### How to Use the script : +``` +Step 1 : First clone the repo +Step 2 : Then install dependencies by python run requirements.txt +step 3 : Input an image to the script +Step 4 : Run the script and see the output +``` diff --git a/image_cartoonizer/imagecartoonizer.py b/image_cartoonizer/imagecartoonizer.py index 5c2fe960d..9fecfc754 100644 --- a/image_cartoonizer/imagecartoonizer.py +++ b/image_cartoonizer/imagecartoonizer.py @@ -1,24 +1,24 @@ -import cv2 -# import numpy as np - -img = cv2.imread(r"input image.jpg") - -# 1) Edges -gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) -gray = cv2.medianBlur(gray, 5) -edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, - cv2.THRESH_BINARY, 9, 9) - -# 2) Color -color = cv2.bilateralFilter(img, 9, 300, 300) - -# 3) Cartoon -cartoon = cv2.bitwise_and(color, color, mask=edges) - - -cv2.imshow("Image", img) -cv2.imshow("Cartoon", cartoon) -cv2.imshow("color", color) -cv2.imshow("edges", edges) -cv2.waitKey(0) -cv2.destroyAllWindows() +import cv2 +# import numpy as np + +img = cv2.imread(r"input image.jpg") + +# 1) Edges +gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) +gray = cv2.medianBlur(gray, 5) +edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, + cv2.THRESH_BINARY, 9, 9) + +# 2) Color +color = cv2.bilateralFilter(img, 9, 300, 300) + +# 3) Cartoon +cartoon = cv2.bitwise_and(color, color, mask=edges) + + +cv2.imshow("Image", img) +cv2.imshow("Cartoon", cartoon) +cv2.imshow("color", color) +cv2.imshow("edges", edges) +cv2.waitKey(0) +cv2.destroyAllWindows() diff --git a/image_cartoonizer/requirements.txt b/image_cartoonizer/requirements.txt index 0808d104b..d3aa7c6cd 100644 --- a/image_cartoonizer/requirements.txt +++ b/image_cartoonizer/requirements.txt @@ -1,2 +1,2 @@ -numpy = 1.19.2 -cv2 = 4.4.0.44 +numpy = 1.19.2 +cv2 = 4.4.0.44 diff --git a/image_resizer/README.md b/image_resizer/README.md index 69ddcd220..7474104b0 100644 --- a/image_resizer/README.md +++ b/image_resizer/README.md @@ -1,39 +1,39 @@ -# Image Resizer - -Resize the .jpeg or .png image to preferred ratio aspect. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -### Pre-requisites -Setup virtual environment from previous step or install requirements manually: -``` -$ pip install opencv-python -``` - -### How to Use -``` -$ python image_resizer.py [-h] [-f F] [-rw RW] [-rh RH] [-n N] -``` - -If not adding any argument, the script will resize demo.jpeg and generate "demo_640x480.jpeg" as default - -``` -optional arguments: - -h, --help show this help message and exit - -f F The file path of target image. ex. /home/user/example.jpeg. - Default value is "demo.jpeg" - -rw RW The new width to be resize. Default value is "640" - -rh RH The new height to be resize. Default value is "480" - -n N The file name. Default value is current {current file - name}_{rw}x{rh}.jpeg -``` - - - - - +# Image Resizer + +Resize the .jpeg or .png image to preferred ratio aspect. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +### Pre-requisites +Setup virtual environment from previous step or install requirements manually: +``` +$ pip install opencv-python +``` + +### How to Use +``` +$ python image_resizer.py [-h] [-f F] [-rw RW] [-rh RH] [-n N] +``` + +If not adding any argument, the script will resize demo.jpeg and generate "demo_640x480.jpeg" as default + +``` +optional arguments: + -h, --help show this help message and exit + -f F The file path of target image. ex. /home/user/example.jpeg. + Default value is "demo.jpeg" + -rw RW The new width to be resize. Default value is "640" + -rh RH The new height to be resize. Default value is "480" + -n N The file name. Default value is current {current file + name}_{rw}x{rh}.jpeg +``` + + + + + diff --git a/image_resizer/image_resizer.py b/image_resizer/image_resizer.py index ca1e91f69..fcb2e4432 100644 --- a/image_resizer/image_resizer.py +++ b/image_resizer/image_resizer.py @@ -1,87 +1,87 @@ -import cv2 -import os -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument( - '-f', - type=str, - help='The file path of target image. ' - + 'ex. /home/user/example.jpeg.\nDefault value is "demo.jpeg"', - default=os.path.dirname(__file__) + '/demo.jpeg' -) -parser.add_argument( - '-rw', - type=int, - help='The new width to be resize.\nDefault value is "640"', - default=640 -) -parser.add_argument( - '-rh', - type=int, - help='The new height to be resize.\nDefault value is "480"', - default=480 -) -parser.add_argument( - '-n', - type=str, - help='The file name.\n' - + 'Default value is current {current file name}_{rw}x{rh}.jpeg', -) - -args = parser.parse_args() -img_path = args.f -resized_width = args.rw -resized_height = args.rh - -if args.n: - new_file = args.n -else: - new_file = (lambda x: x.split('/')[-1].split('.')[0])(args.f) - new_file += f'_{args.rw}x{args.rh}.jpeg' - -# If path is invalid, ask user to input image path again -# and output current image ratio -while True: - img = cv2.imread(img_path) - if img is None: - print( - 'Directory or file is not valid,' - + ' please enter a valid file directory ...') - img_path = str(input('Enter the image path again (absolute path): ')) - else: - break - -original_width = img.shape[0] -original_height = img.shape[1] -print(f'Current image ratio is {original_width} x {original_height}') - -# If stdin rw & rh value larger than original img size -# ask user to input again. -while True: - try: - if resized_width > original_width: - raise RuntimeError( - 'Resized width must be no larger than original width' - + f' (< {original_width})' - ) - if resized_height > original_height: - raise RuntimeError( - 'Resized height must be no larger than original height' - + f' (< {original_height})' - ) - break - except RuntimeError as err: - print(err) - resized_width = int(input('Enter the new width: ')) - resized_height = int(input('Enter the new height: ')) - -# Export new resized image onto the same dir as image_resizer.py -new_img = cv2.resize(img, (resized_width, resized_height)) -cv2.imwrite(f'{os.path.dirname(__file__)}/{new_file}', new_img) - -comment = f'Resized image ({resized_width} x {resized_height})' -comment += ' is now stored on the directory below:' -comment += f'\n{os.path.dirname(__file__)}/{new_file}' - -print(comment) +import cv2 +import os +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument( + '-f', + type=str, + help='The file path of target image. ' + + 'ex. /home/user/example.jpeg.\nDefault value is "demo.jpeg"', + default=os.path.dirname(__file__) + '/demo.jpeg' +) +parser.add_argument( + '-rw', + type=int, + help='The new width to be resize.\nDefault value is "640"', + default=640 +) +parser.add_argument( + '-rh', + type=int, + help='The new height to be resize.\nDefault value is "480"', + default=480 +) +parser.add_argument( + '-n', + type=str, + help='The file name.\n' + + 'Default value is current {current file name}_{rw}x{rh}.jpeg', +) + +args = parser.parse_args() +img_path = args.f +resized_width = args.rw +resized_height = args.rh + +if args.n: + new_file = args.n +else: + new_file = (lambda x: x.split('/')[-1].split('.')[0])(args.f) + new_file += f'_{args.rw}x{args.rh}.jpeg' + +# If path is invalid, ask user to input image path again +# and output current image ratio +while True: + img = cv2.imread(img_path) + if img is None: + print( + 'Directory or file is not valid,' + + ' please enter a valid file directory ...') + img_path = str(input('Enter the image path again (absolute path): ')) + else: + break + +original_width = img.shape[0] +original_height = img.shape[1] +print(f'Current image ratio is {original_width} x {original_height}') + +# If stdin rw & rh value larger than original img size +# ask user to input again. +while True: + try: + if resized_width > original_width: + raise RuntimeError( + 'Resized width must be no larger than original width' + + f' (< {original_width})' + ) + if resized_height > original_height: + raise RuntimeError( + 'Resized height must be no larger than original height' + + f' (< {original_height})' + ) + break + except RuntimeError as err: + print(err) + resized_width = int(input('Enter the new width: ')) + resized_height = int(input('Enter the new height: ')) + +# Export new resized image onto the same dir as image_resizer.py +new_img = cv2.resize(img, (resized_width, resized_height)) +cv2.imwrite(f'{os.path.dirname(__file__)}/{new_file}', new_img) + +comment = f'Resized image ({resized_width} x {resized_height})' +comment += ' is now stored on the directory below:' +comment += f'\n{os.path.dirname(__file__)}/{new_file}' + +print(comment) diff --git a/image_resizer/makefile b/image_resizer/makefile index e78e53c81..7aafa604a 100644 --- a/image_resizer/makefile +++ b/image_resizer/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/image_to_sketch/README.md b/image_to_sketch/README.md index 95485dd9d..16d6136ae 100644 --- a/image_to_sketch/README.md +++ b/image_to_sketch/README.md @@ -1,21 +1,21 @@ -## USER GUIDE - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -### Pre-requisites -``` -1) Python Opencv -$ pip install opencv-contrib-python -``` -### How to run the script? -1) Please the edit the script with the source file location and the destination file location of the photo to be sketched. -2) Run the python script -``` -$ python image_to_sketch.py -``` -Once done the script will prompt with the sketched destination folder. +## USER GUIDE + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +### Pre-requisites +``` +1) Python Opencv +$ pip install opencv-contrib-python +``` +### How to run the script? +1) Please the edit the script with the source file location and the destination file location of the photo to be sketched. +2) Run the python script +``` +$ python image_to_sketch.py +``` +Once done the script will prompt with the sketched destination folder. diff --git a/image_to_sketch/image_to_sketch.py b/image_to_sketch/image_to_sketch.py index 5a6c5e4a0..cd5e55a34 100644 --- a/image_to_sketch/image_to_sketch.py +++ b/image_to_sketch/image_to_sketch.py @@ -1,11 +1,11 @@ -import cv2 - -# Add the source file path here -image_source = ".jpg. - - Thank you +# INSTA PROFILE PIC DOWNLOADER + This is python script which can be useful for downloading the profile picture of a user in Instagram. + + Steps: + + 1. Download Python from https://python.org/downloads/. + 2. Install it and make sure to add it to path variable. + 3. Download this folder and save it in your local machine. + 4. Open command prompt in the folder and run the command. + `pip install -r requirements.txt` + 5. Now run the python script and enter the username of the person. + 6. A picture will be saved automatically in same folder where this python script is located with the name as .jpg. + + Thank you diff --git a/instadp_downloader/insta_profile_pic_download.py b/instadp_downloader/insta_profile_pic_download.py index 36c0100b3..d3f678a95 100644 --- a/instadp_downloader/insta_profile_pic_download.py +++ b/instadp_downloader/insta_profile_pic_download.py @@ -1,27 +1,27 @@ -# import the required libraries -# install these using the command "pip install -r requirements.txt" -# in the command prompt -import requests -from bs4 import BeautifulSoup - -# prompts the user for to take input of username of the person -username = input("Please enter the username: ") -# gives the instagram url -URL = "https://www.instagram.com/{}/" - -# formatting the url by adding username -r = requests.get(URL.format(username)) -# using beatifulsoup library parsing -# the html of the website -s = BeautifulSoup(r.text, "html.parser") - -# finding the image in the url -# using html parser -u = s.find("meta", property="og:image") -url = u.attrs['content'] - -# saving the image the folder -# where this file is saved -with open(username + '.jpg', 'wb') as pic: - binary = requests.get(url).content - pic.write(binary) +# import the required libraries +# install these using the command "pip install -r requirements.txt" +# in the command prompt +import requests +from bs4 import BeautifulSoup + +# prompts the user for to take input of username of the person +username = input("Please enter the username: ") +# gives the instagram url +URL = "https://www.instagram.com/{}/" + +# formatting the url by adding username +r = requests.get(URL.format(username)) +# using beatifulsoup library parsing +# the html of the website +s = BeautifulSoup(r.text, "html.parser") + +# finding the image in the url +# using html parser +u = s.find("meta", property="og:image") +url = u.attrs['content'] + +# saving the image the folder +# where this file is saved +with open(username + '.jpg', 'wb') as pic: + binary = requests.get(url).content + pic.write(binary) diff --git a/instadp_downloader/requirements.txt b/instadp_downloader/requirements.txt index aca37d83a..d8492f3a2 100644 --- a/instadp_downloader/requirements.txt +++ b/instadp_downloader/requirements.txt @@ -1,3 +1,3 @@ -beautifulsoup4 == 4.9.3 -requests == 2.24.0 +beautifulsoup4 == 4.9.3 +requests == 2.24.0 requests-oauthlib == 1.3.0 \ No newline at end of file diff --git a/iplscore_notifier/README.md b/iplscore_notifier/README.md index 28c040e05..99c873c5b 100644 --- a/iplscore_notifier/README.md +++ b/iplscore_notifier/README.md @@ -1,15 +1,15 @@ -# IPL SCORE NOTIFIER -Script that gives Live IPL Scores - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - - -### Execution: -Run the following command on your cmd/linux terminal: - -``$ python score.py`` +# IPL SCORE NOTIFIER +Script that gives Live IPL Scores + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + + +### Execution: +Run the following command on your cmd/linux terminal: + +``$ python score.py`` diff --git a/iplscore_notifier/makefile b/iplscore_notifier/makefile index e78e53c81..7aafa604a 100644 --- a/iplscore_notifier/makefile +++ b/iplscore_notifier/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/iplscore_notifier/requirements.txt b/iplscore_notifier/requirements.txt index 418f6582f..8737e52ab 100644 --- a/iplscore_notifier/requirements.txt +++ b/iplscore_notifier/requirements.txt @@ -1,2 +1,2 @@ -pycricbuzz==2.4 -win10toast==0.9 +pycricbuzz==2.4 +win10toast==0.9 diff --git a/iplscore_notifier/score.py b/iplscore_notifier/score.py index ba15395a8..4451b23ef 100644 --- a/iplscore_notifier/score.py +++ b/iplscore_notifier/score.py @@ -1,71 +1,71 @@ -from pycricbuzz import Cricbuzz -from win10toast import ToastNotifier - -c = Cricbuzz() -n = ToastNotifier() -matches = c.matches() - -srs_to_watch = "Indian Premier League 2020" -match_id = [] - - -def match_info(mid): - c = Cricbuzz() - minfo = c.matchinfo(mid) - - print('------------------------------------------') - print(" Match No : " + minfo["mnum"]) - print(" Match Between : " + minfo["team1"]["name"] + " v/s " + minfo["team2"]["name"]) - - if(minfo["toss"] == ""): - print(" Toss is yet to happen") - else: - print(" Toss : " + minfo["toss"]) - - print(" Match Location : " + minfo["venue_name"] + " located at " + minfo["venue_location"]) - print(" Match Status : " + minfo["status"]) - - -def live_score(mid): - - c = Cricbuzz() - lscore = c.livescore(mid) - - if lscore == {}: - pass - else: - print("-------------------------------------------") - print("Innings No : " + lscore["batting"]["score"][0]["inning_num"]) - print(lscore["batting"]["team"] + " : " + lscore["batting"]["score"][0]["runs"] + "/" - + lscore["batting"]["score"][0]["wickets"] + " in " + lscore["batting"]["score"][0]["overs"] + " overs") - - message = (lscore["batting"]["team"] + " : " + lscore["batting"]["score"][0]["runs"] + "/" - + lscore["batting"]["score"][0]["wickets"] + " in " + lscore["batting"]["score"][0]["overs"] - + " overs") - - n.show_toast("LIVE MATCH SCORE", message, duration=10) - - -for i in matches: - if(i["srs"] == srs_to_watch): - match_id.append(i["id"]) - -print("Match Details Available : ") -for id in match_id: - match_info(id) - -while True: - - print("Live Score of the ongoing/over match is as follows : ") - for id in match_id: - live_score(id) - - message = input("Do you want to refresh the score ? [Y/N]") - - if message == "Y": - print('------------------------------------------') - elif message == "N": - break - else: - print('Please enter "Y" or "N" only.') - continue +from pycricbuzz import Cricbuzz +from win10toast import ToastNotifier + +c = Cricbuzz() +n = ToastNotifier() +matches = c.matches() + +srs_to_watch = "Indian Premier League 2020" +match_id = [] + + +def match_info(mid): + c = Cricbuzz() + minfo = c.matchinfo(mid) + + print('------------------------------------------') + print(" Match No : " + minfo["mnum"]) + print(" Match Between : " + minfo["team1"]["name"] + " v/s " + minfo["team2"]["name"]) + + if(minfo["toss"] == ""): + print(" Toss is yet to happen") + else: + print(" Toss : " + minfo["toss"]) + + print(" Match Location : " + minfo["venue_name"] + " located at " + minfo["venue_location"]) + print(" Match Status : " + minfo["status"]) + + +def live_score(mid): + + c = Cricbuzz() + lscore = c.livescore(mid) + + if lscore == {}: + pass + else: + print("-------------------------------------------") + print("Innings No : " + lscore["batting"]["score"][0]["inning_num"]) + print(lscore["batting"]["team"] + " : " + lscore["batting"]["score"][0]["runs"] + "/" + + lscore["batting"]["score"][0]["wickets"] + " in " + lscore["batting"]["score"][0]["overs"] + " overs") + + message = (lscore["batting"]["team"] + " : " + lscore["batting"]["score"][0]["runs"] + "/" + + lscore["batting"]["score"][0]["wickets"] + " in " + lscore["batting"]["score"][0]["overs"] + + " overs") + + n.show_toast("LIVE MATCH SCORE", message, duration=10) + + +for i in matches: + if(i["srs"] == srs_to_watch): + match_id.append(i["id"]) + +print("Match Details Available : ") +for id in match_id: + match_info(id) + +while True: + + print("Live Score of the ongoing/over match is as follows : ") + for id in match_id: + live_score(id) + + message = input("Do you want to refresh the score ? [Y/N]") + + if message == "Y": + print('------------------------------------------') + elif message == "N": + break + else: + print('Please enter "Y" or "N" only.') + continue diff --git a/key_logger/README.md b/key_logger/README.md index 303a388f9..f5326f493 100644 --- a/key_logger/README.md +++ b/key_logger/README.md @@ -1,32 +1,32 @@ -# Keylogger using pynput module -A python script that records every keystroke made by a computer user and saves it in a text file with timestamp of the key being pressed. - -If you want to run the program in background without creating a console window., save the file with the extension .pyw. -Example : _keylogger.pyw_ - -## Modules Used - -- pynput -- logging - -We need to install the pynput module. To install the module type the following into the terminal: -```bash -pip install pynput -``` - -Recommended: Install the module after creating a virtual environment. - -## Execution -- To run the program, type the following command into your terminal - -```bash -python keylogger.py -``` - -- OR -```bash -python keylogger.pyw -``` - -The keystrokes are now being logged into the logs.txt file. +# Keylogger using pynput module +A python script that records every keystroke made by a computer user and saves it in a text file with timestamp of the key being pressed. + +If you want to run the program in background without creating a console window., save the file with the extension .pyw. +Example : _keylogger.pyw_ + +## Modules Used + +- pynput +- logging + +We need to install the pynput module. To install the module type the following into the terminal: +```bash +pip install pynput +``` + +Recommended: Install the module after creating a virtual environment. + +## Execution +- To run the program, type the following command into your terminal + +```bash +python keylogger.py +``` + +- OR +```bash +python keylogger.pyw +``` + +The keystrokes are now being logged into the logs.txt file. To stop recording the keystrokes terminate the program. \ No newline at end of file diff --git a/key_logger/keylogger.py b/key_logger/keylogger.py index 311a86536..890c07115 100644 --- a/key_logger/keylogger.py +++ b/key_logger/keylogger.py @@ -1,18 +1,18 @@ -import logging -from pynput.keyboard import Listener - - -def keylogger_py(): - log_destination = "" - logging.basicConfig(filename=(log_destination + "logs.txt"), - level=logging.DEBUG, - format='%(asctime)s : %(message)s') - - def keypress(key): - logging.info(str(key)) - - with Listener(on_press=keypress) as listener: - listener.join() - - -keylogger_py() +import logging +from pynput.keyboard import Listener + + +def keylogger_py(): + log_destination = "" + logging.basicConfig(filename=(log_destination + "logs.txt"), + level=logging.DEBUG, + format='%(asctime)s : %(message)s') + + def keypress(key): + logging.info(str(key)) + + with Listener(on_press=keypress) as listener: + listener.join() + + +keylogger_py() diff --git a/language_translator/README.md b/language_translator/README.md index bdb64abf9..7ce061a5f 100644 --- a/language_translator/README.md +++ b/language_translator/README.md @@ -1,19 +1,19 @@ -## USER GUIDE - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -### Pre-requisites -``` -1) Googletrans python library -$ pip install googletrans -``` -### How to run the script? -``` -$ python we-can-use-google-trans.py -``` -Once done the script will prompt for input. +## USER GUIDE + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +### Pre-requisites +``` +1) Googletrans python library +$ pip install googletrans +``` +### How to run the script? +``` +$ python we-can-use-google-trans.py +``` +Once done the script will prompt for input. diff --git a/language_translator/makefile b/language_translator/makefile index e78e53c81..7aafa604a 100644 --- a/language_translator/makefile +++ b/language_translator/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/language_translator/we-can-use-google-trans.py b/language_translator/we-can-use-google-trans.py index f36991a4b..cc6787fc9 100644 --- a/language_translator/we-can-use-google-trans.py +++ b/language_translator/we-can-use-google-trans.py @@ -1,15 +1,15 @@ -import googletrans -from googletrans import Translator - -# Get the list of languages from the google translate API -langList = googletrans.LANGUAGES -# Get the input from the user -inputSentence = input("Please enter a sentence to translate :\n") -translator = Translator() -# Detect the Language -sourceLang = translator.detect(inputSentence).lang -sourceLang = langList[sourceLang] -# Get the translation -translateString = translator.translate(inputSentence).text - -print("The language detected was: " + sourceLang + "\n" + "The translation is: " + translateString) +import googletrans +from googletrans import Translator + +# Get the list of languages from the google translate API +langList = googletrans.LANGUAGES +# Get the input from the user +inputSentence = input("Please enter a sentence to translate :\n") +translator = Translator() +# Detect the Language +sourceLang = translator.detect(inputSentence).lang +sourceLang = langList[sourceLang] +# Get the translation +translateString = translator.translate(inputSentence).text + +print("The language detected was: " + sourceLang + "\n" + "The translation is: " + translateString) diff --git a/links_extractor/README.md b/links_extractor/README.md index 615c73d78..02b362fe9 100644 --- a/links_extractor/README.md +++ b/links_extractor/README.md @@ -1,13 +1,13 @@ -# Links Extractor - -## Objective -This script automate extracting URLs from any ```.txt``` file content based on regex expression then exporting the extracted urls in ```.txt``` output file separated by line separator. -## Sample -- Sample input available in ```sample/sample_text_file.txt``` -- Sample output available in ```sample/sample_text_file_links.txt``` -## Requirements -```pip install requirements.txt``` -## How to run the script? -``` -python links_extractor.py file_name.txt -``` +# Links Extractor + +## Objective +This script automate extracting URLs from any ```.txt``` file content based on regex expression then exporting the extracted urls in ```.txt``` output file separated by line separator. +## Sample +- Sample input available in ```sample/sample_text_file.txt``` +- Sample output available in ```sample/sample_text_file_links.txt``` +## Requirements +```pip install requirements.txt``` +## How to run the script? +``` +python links_extractor.py file_name.txt +``` diff --git a/links_extractor/links_extractor.py b/links_extractor/links_extractor.py index 075a88056..193148f12 100644 --- a/links_extractor/links_extractor.py +++ b/links_extractor/links_extractor.py @@ -1,57 +1,57 @@ -import re -import sys - - -def get_urls(file_path): - """[start method to fire extracting urls process] - - Arguments: - file_path {[str]} -- [target text file path] - """ - text = read_text_file(file_path) - urls = extract_urls(text) - export_urls(urls, file_path) - - -def read_text_file(file_path): - """[summary] - - Arguments: - file_path {[str]} -- [target text file path] - - Returns: - [str] -- [file content to works on] - """ - with open(file_path) as f: - text = f.read() - return text - - -def extract_urls(text): - """[summary] - - Arguments: - text {[str]} -- [file content to works on] - - Returns: - [list] -- [extracted urls] - """ - url_regex_pattern = r"(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+" - urls = re.findall(url_regex_pattern, text) - return urls - - -def export_urls(urls, file_path): - """[summary] - - Arguments: - urls {[list]} -- [extracted urls] - file_path {[str]} -- [result text file path] - """ - with open(file_path.replace(".txt", "_links.txt"), "w") as f: - f.write("\n".join(urls)) - - -if __name__ == "__main__": - file_path = sys.argv[1] - get_urls(file_path) +import re +import sys + + +def get_urls(file_path): + """[start method to fire extracting urls process] + + Arguments: + file_path {[str]} -- [target text file path] + """ + text = read_text_file(file_path) + urls = extract_urls(text) + export_urls(urls, file_path) + + +def read_text_file(file_path): + """[summary] + + Arguments: + file_path {[str]} -- [target text file path] + + Returns: + [str] -- [file content to works on] + """ + with open(file_path) as f: + text = f.read() + return text + + +def extract_urls(text): + """[summary] + + Arguments: + text {[str]} -- [file content to works on] + + Returns: + [list] -- [extracted urls] + """ + url_regex_pattern = r"(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+" + urls = re.findall(url_regex_pattern, text) + return urls + + +def export_urls(urls, file_path): + """[summary] + + Arguments: + urls {[list]} -- [extracted urls] + file_path {[str]} -- [result text file path] + """ + with open(file_path.replace(".txt", "_links.txt"), "w") as f: + f.write("\n".join(urls)) + + +if __name__ == "__main__": + file_path = sys.argv[1] + get_urls(file_path) diff --git a/links_extractor/sample/sample_text_file.txt b/links_extractor/sample/sample_text_file.txt index 1d0b463eb..5c81926c2 100644 --- a/links_extractor/sample/sample_text_file.txt +++ b/links_extractor/sample/sample_text_file.txt @@ -1,13 +1,13 @@ -New album 'Heart To Mouth" is out now: https://lp.lnk.to/HeartToMouthID - - -Lost On You: http://smarturl.it/LostOnYouAlbum - ----------------------------------- - -Website: http://iamlp.com -Facebook: http://facebook.com/iamLP -Twitter: http://twitter.com/iamlp -Soundcloud: https://soundcloud.com/iamlpmusic -Suggested by WMG -LP - Muddy Waters [Live Session] +New album 'Heart To Mouth" is out now: https://lp.lnk.to/HeartToMouthID + + +Lost On You: http://smarturl.it/LostOnYouAlbum + +---------------------------------- + +Website: http://iamlp.com +Facebook: http://facebook.com/iamLP +Twitter: http://twitter.com/iamlp +Soundcloud: https://soundcloud.com/iamlpmusic +Suggested by WMG +LP - Muddy Waters [Live Session] diff --git a/links_extractor/sample/sample_text_file_links.txt b/links_extractor/sample/sample_text_file_links.txt index 7893d2b46..24b166df4 100644 --- a/links_extractor/sample/sample_text_file_links.txt +++ b/links_extractor/sample/sample_text_file_links.txt @@ -1,6 +1,6 @@ -https://lp.lnk.to/HeartToMouthID -http://smarturl.it/LostOnYouAlbum -http://iamlp.com -http://facebook.com/iamLP -http://twitter.com/iamlp +https://lp.lnk.to/HeartToMouthID +http://smarturl.it/LostOnYouAlbum +http://iamlp.com +http://facebook.com/iamLP +http://twitter.com/iamlp https://soundcloud.com/iamlpmusic \ No newline at end of file diff --git a/medium_to_pdf/README.md b/medium_to_pdf/README.md index a8f4387a4..8f519c86a 100644 --- a/medium_to_pdf/README.md +++ b/medium_to_pdf/README.md @@ -1,21 +1,21 @@ -# Medium Article PDF Downloader. - -## Module Used. -- pdfkit - -## How to use. -- Download the folder `medium-to-pdf`. -- Create virtual enviroment. - - `virtualenv env` -- Activate It. - - `. ./env/bin/activate` -- Install `wkhtmltopdf`. - - In Ubuntu/Debian: - - `apt-get install wkhtmltopdf` - - For installation on other platforms. - - https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf -- Install python dependencies. - - `pip install -r ./requirements.txt` -- Finally Use the file `main.py`. - - `python ./main.py --url --output ` - +# Medium Article PDF Downloader. + +## Module Used. +- pdfkit + +## How to use. +- Download the folder `medium-to-pdf`. +- Create virtual enviroment. + - `virtualenv env` +- Activate It. + - `. ./env/bin/activate` +- Install `wkhtmltopdf`. + - In Ubuntu/Debian: + - `apt-get install wkhtmltopdf` + - For installation on other platforms. + - https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf +- Install python dependencies. + - `pip install -r ./requirements.txt` +- Finally Use the file `main.py`. + - `python ./main.py --url --output ` + diff --git a/medium_to_pdf/main.py b/medium_to_pdf/main.py index a1e8f2cc8..58c0effea 100644 --- a/medium_to_pdf/main.py +++ b/medium_to_pdf/main.py @@ -1,38 +1,38 @@ -#!/usr/bin/env python -import pdfkit -import sys - - -class MediumToPdf(): - """ - This class contains method to convert a medium article into pdf file. - """ - def __init__(self, url, output_file): - """ - url: The url of medium article. - output_file: The name of the output file. - """ - self.convert_to_pdf(url, output_file) - - def convert_to_pdf(self, url, output_file): - """ - url: The url of medium article. - output_file: The name of the output file. - """ - options = { - 'page-size': 'A4', - 'margin-top': '0.75in', - 'margin-right': '0.75in', - 'margin-bottom': '0.75in', - 'margin-left': '0.75in', - } - pdfkit.from_url(url, output_file, options=options) - - -if __name__ == "__main__": - url = sys.argv[sys.argv.index('--url') + 1] - output_file = sys.argv[sys.argv.index('--output') + 1] - try: - medium_to_pdf = MediumToPdf(url, output_file) - except Exception as e: - print("An error arised. ", e) +#!/usr/bin/env python +import pdfkit +import sys + + +class MediumToPdf(): + """ + This class contains method to convert a medium article into pdf file. + """ + def __init__(self, url, output_file): + """ + url: The url of medium article. + output_file: The name of the output file. + """ + self.convert_to_pdf(url, output_file) + + def convert_to_pdf(self, url, output_file): + """ + url: The url of medium article. + output_file: The name of the output file. + """ + options = { + 'page-size': 'A4', + 'margin-top': '0.75in', + 'margin-right': '0.75in', + 'margin-bottom': '0.75in', + 'margin-left': '0.75in', + } + pdfkit.from_url(url, output_file, options=options) + + +if __name__ == "__main__": + url = sys.argv[sys.argv.index('--url') + 1] + output_file = sys.argv[sys.argv.index('--output') + 1] + try: + medium_to_pdf = MediumToPdf(url, output_file) + except Exception as e: + print("An error arised. ", e) diff --git a/medium_to_pdf/requirements.txt b/medium_to_pdf/requirements.txt index da9d589d7..697b19aa7 100644 --- a/medium_to_pdf/requirements.txt +++ b/medium_to_pdf/requirements.txt @@ -1 +1 @@ -pdfkit==0.6.1 +pdfkit==0.6.1 diff --git a/music_player/README.md b/music_player/README.md index 9a4a3afa9..5e2e0c581 100644 --- a/music_player/README.md +++ b/music_player/README.md @@ -1,27 +1,27 @@ -# Music Player -A simple music player with gui written in python - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## Modules Used - -- vlc -- tkinter - -## Requirements - -- vlc -`pip install python-vlc` - -- tkinter -`https://tkdocs.com/tutorial/install.html` - -## How to use -`python player.py` - -After gui started you can pick song with "Pick Music" button +# Music Player +A simple music player with gui written in python + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## Modules Used + +- vlc +- tkinter + +## Requirements + +- vlc +`pip install python-vlc` + +- tkinter +`https://tkdocs.com/tutorial/install.html` + +## How to use +`python player.py` + +After gui started you can pick song with "Pick Music" button diff --git a/music_player/makefile b/music_player/makefile index e78e53c81..7aafa604a 100644 --- a/music_player/makefile +++ b/music_player/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/music_player/player.py b/music_player/player.py index 57fee19d8..6cfeaae26 100644 --- a/music_player/player.py +++ b/music_player/player.py @@ -1,100 +1,100 @@ -import tkinter as tk -from tkinter import RIGHT, TOP, CENTER, X -from tkinter.filedialog import Button, Tk -from tkinter import filedialog -import vlc - -# Define root -root = Tk() -root.title("Music Player") - -# Set default label text -label_text = tk.StringVar() -label_text.set("") - - -def pick_music(): - global music_path, label_text - # Get chosen files path - music_path = filedialog.askopenfilename( - filetypes=(("mp3 files", "*.mp3"), ("waw files", "*.waw"))) - # Set music name label text - label_text.set(music_path.split("/")[-1]) - # Set button states to normal - stop_music_button["state"] = "normal" - pause_music_button["state"] = "normal" - play_music_button["state"] = "normal" - - -def play_music(): - global p - # If song playing try to stop - try: - p.stop() - except Exception: - pass - p = vlc.MediaPlayer(r"file:///" + music_path) - # Start music - p.play() - # Change play button state to disabled - play_music_button["state"] = "disabled" - - -def stop_music(): - p.stop() - play_music_button["state"] = "normal" - - -def pause_music(): - p.pause() - - -# Pick music button -pck_btn = Button( - root, - text="Pick Music", - font="Rockwell", - relief="flat", - command=pick_music) -pck_btn.pack(side=TOP) - -# Music name label -msc_nme_lbl = tk.Label( - root, - justify=CENTER, - textvariable=label_text) -msc_nme_lbl.pack(side=TOP, fill=X, padx=10) - -# Stop music button -stop_music_button = Button( - root, - text="Stop", - font="Rockwell", - relief="flat", - command=stop_music) -stop_music_button.pack(side=RIGHT) - -# Pause music button -pause_music_button = Button( - root, - text="Pause", - font="Rockwell", - relief="flat", - command=pause_music) -pause_music_button.pack(side=RIGHT) - -# Play music button -play_music_button = Button( - root, - text="Play", - font="Rockwell", - relief="flat", - command=play_music) -play_music_button.pack(side=RIGHT) - -# Set default button satates to disabled -stop_music_button["state"] = "disabled" -pause_music_button["state"] = "disabled" -play_music_button["state"] = "disabled" - -root.mainloop() +import tkinter as tk +from tkinter import RIGHT, TOP, CENTER, X +from tkinter.filedialog import Button, Tk +from tkinter import filedialog +import vlc + +# Define root +root = Tk() +root.title("Music Player") + +# Set default label text +label_text = tk.StringVar() +label_text.set("") + + +def pick_music(): + global music_path, label_text + # Get chosen files path + music_path = filedialog.askopenfilename( + filetypes=(("mp3 files", "*.mp3"), ("waw files", "*.waw"))) + # Set music name label text + label_text.set(music_path.split("/")[-1]) + # Set button states to normal + stop_music_button["state"] = "normal" + pause_music_button["state"] = "normal" + play_music_button["state"] = "normal" + + +def play_music(): + global p + # If song playing try to stop + try: + p.stop() + except Exception: + pass + p = vlc.MediaPlayer(r"file:///" + music_path) + # Start music + p.play() + # Change play button state to disabled + play_music_button["state"] = "disabled" + + +def stop_music(): + p.stop() + play_music_button["state"] = "normal" + + +def pause_music(): + p.pause() + + +# Pick music button +pck_btn = Button( + root, + text="Pick Music", + font="Rockwell", + relief="flat", + command=pick_music) +pck_btn.pack(side=TOP) + +# Music name label +msc_nme_lbl = tk.Label( + root, + justify=CENTER, + textvariable=label_text) +msc_nme_lbl.pack(side=TOP, fill=X, padx=10) + +# Stop music button +stop_music_button = Button( + root, + text="Stop", + font="Rockwell", + relief="flat", + command=stop_music) +stop_music_button.pack(side=RIGHT) + +# Pause music button +pause_music_button = Button( + root, + text="Pause", + font="Rockwell", + relief="flat", + command=pause_music) +pause_music_button.pack(side=RIGHT) + +# Play music button +play_music_button = Button( + root, + text="Play", + font="Rockwell", + relief="flat", + command=play_music) +play_music_button.pack(side=RIGHT) + +# Set default button satates to disabled +stop_music_button["state"] = "disabled" +pause_music_button["state"] = "disabled" +play_music_button["state"] = "disabled" + +root.mainloop() diff --git a/music_player/requirements.txt b/music_player/requirements.txt index 3480d9a14..176f4c8ce 100644 --- a/music_player/requirements.txt +++ b/music_player/requirements.txt @@ -1 +1 @@ -python-vlc +python-vlc diff --git a/password_checker/makefile b/password_checker/makefile index e78e53c81..7aafa604a 100644 --- a/password_checker/makefile +++ b/password_checker/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/password_checker/password_strength_checker.py b/password_checker/password_strength_checker.py index 4b14ee83c..9116169d9 100644 --- a/password_checker/password_strength_checker.py +++ b/password_checker/password_strength_checker.py @@ -1,16 +1,16 @@ -import sys -import re - -password = sys.argv[1] -regex = re.compile('[@_!#$%^&*()<>?/|}{~:]') - -t1 = len(password) >= 8 -t2 = not (regex.search(password) is None) -t3 = any(c.islower() for c in password) -t4 = any(c.isupper() for c in password) -t5 = any(c.isdigit() for c in password) - -if t1 and t2 and t3 and t4 and t5: - print("Password is STRONG") -else: - print("Password is WEAK") +import sys +import re + +password = sys.argv[1] +regex = re.compile('[@_!#$%^&*()<>?/|}{~:]') + +t1 = len(password) >= 8 +t2 = not (regex.search(password) is None) +t3 = any(c.islower() for c in password) +t4 = any(c.isupper() for c in password) +t5 = any(c.isdigit() for c in password) + +if t1 and t2 and t3 and t4 and t5: + print("Password is STRONG") +else: + print("Password is WEAK") diff --git a/password_checker/readme.md b/password_checker/readme.md index 9bf4da7df..d817fc7be 100644 --- a/password_checker/readme.md +++ b/password_checker/readme.md @@ -1,23 +1,23 @@ -Password Strength Checker is a simple python scrpt to check if a given password is strong or not. - -It checks the following things to decide the strength of a password -- at least characters in length -- at least one lowercase character -- at least one uppercase character -- at least one digit (0-9) -- at least one special character [@_!#$%^&*()<>?/\|}{~:] - -**Requirements** -- python3 - -**Setup virtual environment** - -```make init``` - -**Modules used** -- sys -- re - -**HOW TO RUN IN TERMINAL** - -> python3 password_strength_checker.py *sample_password* +Password Strength Checker is a simple python scrpt to check if a given password is strong or not. + +It checks the following things to decide the strength of a password +- at least characters in length +- at least one lowercase character +- at least one uppercase character +- at least one digit (0-9) +- at least one special character [@_!#$%^&*()<>?/\|}{~:] + +**Requirements** +- python3 + +**Setup virtual environment** + +```make init``` + +**Modules used** +- sys +- re + +**HOW TO RUN IN TERMINAL** + +> python3 password_strength_checker.py *sample_password* diff --git a/password_manager/README.md b/password_manager/README.md index 48bb993fb..362110842 100644 --- a/password_manager/README.md +++ b/password_manager/README.md @@ -1,25 +1,25 @@ -# Password Manager - - -A simple password manager cli-based, simple, fast and useful. - -[![Python: 3.7](https://img.shields.io/badge/python-3.7-blue)](https://www.python.org/) -[![Build Status](https://img.shields.io/badge/build-passing-success)](https://github.com/ebsa491) - -### Installation - -```shell -(SOURCE_DIR)$ pip3 install -r requirements.txt -``` - -### Usage - -```shell -(SOURCE_DIR)$ python3 password_manager.py [-p, --password] [PASSWORD] -``` - -### Other -By Sam Ebison - -If you have found any important bug or vulnerability, +# Password Manager + + +A simple password manager cli-based, simple, fast and useful. + +[![Python: 3.7](https://img.shields.io/badge/python-3.7-blue)](https://www.python.org/) +[![Build Status](https://img.shields.io/badge/build-passing-success)](https://github.com/ebsa491) + +### Installation + +```shell +(SOURCE_DIR)$ pip3 install -r requirements.txt +``` + +### Usage + +```shell +(SOURCE_DIR)$ python3 password_manager.py [-p, --password] [PASSWORD] +``` + +### Other +By Sam Ebison + +If you have found any important bug or vulnerability, contact me pls, I love learning ( email: ebsa491@gmail.com ) \ No newline at end of file diff --git a/password_manager/password_manager.py b/password_manager/password_manager.py index 7e5feaf63..29dab5467 100755 --- a/password_manager/password_manager.py +++ b/password_manager/password_manager.py @@ -1,430 +1,430 @@ -#!/usr/bin/python3 -# Created by Sam Ebison ( https://github.com/ebsa491 ) -# If you have found any important bug or vulnerability, -# contact me pls, I love learning ( email: ebsa491@gmail.com ) - -""" -This is a simple password manager CLI program -based on https://github.com/python-geeks/Automation-scripts/issues/111 -""" - -import argparse -import sys -import os -import sqlite3 -import base64 -import signal -from getpass import getpass -from Crypto.Cipher import AES -from Crypto.Hash import SHA256 -from Crypto import Random - -# The program data file. -FILENAME = ".pass.db" - -# Cookie(canary) value -COOKIE = "===PASSWORDS===" - -# For coloring the outputs -GREEN_COLOR = "\033[1;32m" -RED_COLOR = "\033[1;31m" -NO_COLOR = "\033[0m" - - -def main(): - """The main function of the program.""" - - status, is_first = check_database() # status{0|-1} is_first{True|False} - - if status == -1: - # ERROR - print(f"[{RED_COLOR}-{NO_COLOR}] Error in database connection...") - sys.exit(1) - - if args.password == '' or args.password is None: - - # User didn't enter the password (argument) - if is_first: - - # New user - user_password = getpass("Enter a new password for the program> ") - confirm = getpass("Confirm it> ") - - if user_password != confirm: - # ERROR - print(f"[{RED_COLOR}-{NO_COLOR}] Didn't match...") - sys.exit(1) - - if new(user_password, COOKIE, '-', 0) != 0: - # ERROR (Cookie didn't set) - print(f"[{RED_COLOR}-{NO_COLOR}] Error in saving...") - os.remove(FILENAME) - sys.exit(1) - - else: - - user_password = getpass("Enter your user password> ") - - if check_password(user_password) != 0: - # ERROR - print(f"[{RED_COLOR}-{NO_COLOR}] Wrong password...") - sys.exit(1) - - else: - - # We have the password here - user_password = args.password - - if check_password(user_password) != 0: - # ERROR - print(f"[{RED_COLOR}-{NO_COLOR}] Wrong password...") - sys.exit(1) - - prompt(user_password) - - -def check_database(): - """ - This function checks the database file. - If everything was going OK returns 0, is_first{True|False} - and if not returns -1, False. - If is_first was True that means the program has run for the first time. - """ - - try: - - # If it was True that means the program has run for the first time - is_first = False - - if not os.path.isfile(FILENAME): - is_first = True - - with sqlite3.connect(FILENAME) as conn: - cursor = conn.cursor() - cursor.execute( - """CREATE TABLE IF NOT EXISTS passwords ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - password TEXT NOT NULL - );""" - ) - - return 0, is_first - except Exception: - return -1, False - - -def check_password(user_password): - """ - This function checks the user password and will return two values {0|-1}, - 0 means the password is correct, - -1 means it's wrong. - """ - - try: - with sqlite3.connect(FILENAME) as conn: - cursor = conn.cursor() - # Fetches the cookie (canary) value - row = cursor.execute( - "SELECT * FROM passwords WHERE id=0;" - ).fetchone() - - bin_user_password = str(user_password).encode('utf-8') - - if decrypt(bin_user_password, row[1]).decode('utf-8') == COOKIE: - # The password is correct - # because it can decrypt the encrypted cookie value - return 0 - else: - # The password can't decrypt the cookie value (Wrong) - return -1 - except Exception: - return -1 - - -def prompt(user_password): - """ - This function will be called after checking the password and database. - It gives you a prompt for entering your commands. - Valid commands are 'new', 'delete', 'show', 'exit'. - """ - - print("Commands: [new] [delete] [show] [exit]") - - try: - cmd = input("Enter your command> ") - except EOFError: - print("\nBye...") - sys.exit(0) - - if cmd.lower() == 'new': - - name = input("Where did you use this password for> ") - password = input("Enter the new password to save> ") - - if new(user_password, name, password) == 0: - - # Row added - print(f"[{GREEN_COLOR}+{NO_COLOR}] Successfully added...") - prompt(user_password) - - else: - - # ERROR - print( - f"[{RED_COLOR}-{NO_COLOR}] Error while writing the password..." - ) - prompt(user_password) - - elif cmd.lower() == 'delete': - - id_num = input("Which id? > ") - confirm = input("Are you sure [Y/n]> ") - - if confirm.lower() == 'y': - - if delete(id_num) == 0: - # Row deleted - print(f"[{GREEN_COLOR}+{NO_COLOR}] Successfully deleted...") - else: - # ERROR - print(f"[{RED_COLOR}-{NO_COLOR}] Error in deleting...") - - prompt(user_password) - - elif cmd.lower() == 'show': - - result = select_data(user_password) - - if result == -1: - # ERROR - print(f"[{RED_COLOR}-{NO_COLOR}] Error in selecting the data...") - else: - show_data(result) - - prompt(user_password) - - elif cmd.lower() == 'exit': - - print("Bye...") - sys.exit(0) - - else: - - print("Command not found...") - prompt(user_password) - - -def new(user_password, name, password, id_num=-1): - """ - This function used for inserting new row to the database. - It will return two values {0|-1}, - 0 means the row has inserted successfully, - -1 means there was an error. - parameters are (in sort) => - =================================== - user_password: The program password, - name: The tag of the new password, - password: The new password, - OPTIONAL id_num: Will be used for specific id number. - """ - - try: - with sqlite3.connect(FILENAME) as conn: - cursor = conn.cursor() - - if id_num == -1: - - # insert id auto-increment - cursor.execute( - """INSERT INTO passwords(name, password) VALUES ( - ?,? - );""", - [ - encrypt( - str(user_password).encode('utf-8'), - str(name).encode('utf-8') - ), - encrypt( - str(user_password).encode('utf-8'), - str(password).encode('utf-8') - ) - ] - ) - - else: - - # insert the given id number - cursor.execute( - """INSERT INTO passwords(id, name, password) VALUES ( - ?,?,? - );""", - [ - id_num, - encrypt( - str(user_password).encode('utf-8'), - str(name).encode('utf-8') - ), - encrypt( - str(user_password).encode('utf-8'), - str(password).encode('utf-8') - ) - ] - ) - - return 0 - except Exception: - return -1 - - -def delete(id_num): - """ - It gets an id number and will delete it from the database. - It will return two values {0|-1} - 0 means the row has deleted successfully, - -1 means there was an error. - """ - - try: - with sqlite3.connect(FILENAME) as conn: - cursor = conn.cursor() - cursor.execute( - "DELETE FROM passwords WHERE id = ? AND name != ?;", - [id_num, COOKIE] - ) - - return 0 - except Exception: - return -1 - - -def select_data(user_password): - """ - This function gets the program password (user_password) - and returns the passwords list. - returning -1 means there was an error - """ - - try: - with sqlite3.connect(FILENAME) as conn: - cursor = conn.cursor() - - # password => id, encrypted name and encrypted password - passwords = cursor.execute("SELECT * FROM passwords;").fetchall() - - # result => id, decrypted name and decrypted password - result = [] - - for (id_num, name, password) in passwords: - result.append( - ( - id_num, - decrypt( - str(user_password).encode('utf-8'), name - ).decode('utf-8'), - decrypt( - str(user_password).encode('utf-8'), password - ).decode('utf-8') - ) - ) - - return result - except Exception: - return -1 - - -def show_data(result): - """ - A function for printing the passwords. - It gets the password list. - """ - - # the length of result must be more than 1 - # because of the cookie row (0, ===PASSWORDS===, -) - if len(result) <= 1: - # Empty - print("\n\n====== Nothing ======\n\n") - else: - - print("\n==============================\n") - - for (id_num, name, password) in result: - if name != COOKIE: - print(f"({id_num}) {name} {GREEN_COLOR}{password}{NO_COLOR}") - - print("\n==============================\n") - - -def encrypt(key, source, encode=True): - """A function for encryption.""" - - # use SHA-256 over our key to get a proper-sized AES key - key = SHA256.new(key).digest() - - # generate iv - iv = Random.new().read(AES.block_size) - encryptor = AES.new(key, AES.MODE_CBC, iv) - - # calculate needed padding - padding = AES.block_size - len(source) % AES.block_size - - # Python 2.x: source += chr(padding) * padding - source += bytes([padding]) * padding - - # store the iv at the beginning and encrypt - data = iv + encryptor.encrypt(source) - return base64.b64encode(data).decode("utf-8") if encode else data - - -def decrypt(key, source, decode=True): - """A function for decrypting the encrypted datum.""" - - if decode: - source = base64.b64decode(source.encode("utf-8")) - - # use SHA-256 over our key to get a proper-sized AES key - key = SHA256.new(key).digest() - - # extract the IV from the beginning - IV = source[:AES.block_size] - decryptor = AES.new(key, AES.MODE_CBC, IV) - - # decrypt - data = decryptor.decrypt(source[AES.block_size:]) - - # pick the padding value from the end; Python 2.x: ord(data[-1]) - padding = data[-1] - - if data[-padding:] != bytes([padding]) * padding: - raise ValueError("Invalid padding...") - - # remove the padding - return data[:-padding] - - -def exit_program(sig, frame): - """For handling SIGINT signal.""" - - print("\nBye...") - sys.exit(0) - - -if __name__ == '__main__': - global args # The program arguments - - parser = argparse.ArgumentParser(description="Password Manager CLI") - # -p | --password PASSWORD - parser.add_argument( - '-p', - '--password', - metavar='password', - type=str, - default='', - help='the program password' - ) - args = parser.parse_args() - - # Handle SIGINT (same as ^C) signal - signal.signal(signal.SIGINT, exit_program) - - main() +#!/usr/bin/python3 +# Created by Sam Ebison ( https://github.com/ebsa491 ) +# If you have found any important bug or vulnerability, +# contact me pls, I love learning ( email: ebsa491@gmail.com ) + +""" +This is a simple password manager CLI program +based on https://github.com/python-geeks/Automation-scripts/issues/111 +""" + +import argparse +import sys +import os +import sqlite3 +import base64 +import signal +from getpass import getpass +from Crypto.Cipher import AES +from Crypto.Hash import SHA256 +from Crypto import Random + +# The program data file. +FILENAME = ".pass.db" + +# Cookie(canary) value +COOKIE = "===PASSWORDS===" + +# For coloring the outputs +GREEN_COLOR = "\033[1;32m" +RED_COLOR = "\033[1;31m" +NO_COLOR = "\033[0m" + + +def main(): + """The main function of the program.""" + + status, is_first = check_database() # status{0|-1} is_first{True|False} + + if status == -1: + # ERROR + print(f"[{RED_COLOR}-{NO_COLOR}] Error in database connection...") + sys.exit(1) + + if args.password == '' or args.password is None: + + # User didn't enter the password (argument) + if is_first: + + # New user + user_password = getpass("Enter a new password for the program> ") + confirm = getpass("Confirm it> ") + + if user_password != confirm: + # ERROR + print(f"[{RED_COLOR}-{NO_COLOR}] Didn't match...") + sys.exit(1) + + if new(user_password, COOKIE, '-', 0) != 0: + # ERROR (Cookie didn't set) + print(f"[{RED_COLOR}-{NO_COLOR}] Error in saving...") + os.remove(FILENAME) + sys.exit(1) + + else: + + user_password = getpass("Enter your user password> ") + + if check_password(user_password) != 0: + # ERROR + print(f"[{RED_COLOR}-{NO_COLOR}] Wrong password...") + sys.exit(1) + + else: + + # We have the password here + user_password = args.password + + if check_password(user_password) != 0: + # ERROR + print(f"[{RED_COLOR}-{NO_COLOR}] Wrong password...") + sys.exit(1) + + prompt(user_password) + + +def check_database(): + """ + This function checks the database file. + If everything was going OK returns 0, is_first{True|False} + and if not returns -1, False. + If is_first was True that means the program has run for the first time. + """ + + try: + + # If it was True that means the program has run for the first time + is_first = False + + if not os.path.isfile(FILENAME): + is_first = True + + with sqlite3.connect(FILENAME) as conn: + cursor = conn.cursor() + cursor.execute( + """CREATE TABLE IF NOT EXISTS passwords ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + password TEXT NOT NULL + );""" + ) + + return 0, is_first + except Exception: + return -1, False + + +def check_password(user_password): + """ + This function checks the user password and will return two values {0|-1}, + 0 means the password is correct, + -1 means it's wrong. + """ + + try: + with sqlite3.connect(FILENAME) as conn: + cursor = conn.cursor() + # Fetches the cookie (canary) value + row = cursor.execute( + "SELECT * FROM passwords WHERE id=0;" + ).fetchone() + + bin_user_password = str(user_password).encode('utf-8') + + if decrypt(bin_user_password, row[1]).decode('utf-8') == COOKIE: + # The password is correct + # because it can decrypt the encrypted cookie value + return 0 + else: + # The password can't decrypt the cookie value (Wrong) + return -1 + except Exception: + return -1 + + +def prompt(user_password): + """ + This function will be called after checking the password and database. + It gives you a prompt for entering your commands. + Valid commands are 'new', 'delete', 'show', 'exit'. + """ + + print("Commands: [new] [delete] [show] [exit]") + + try: + cmd = input("Enter your command> ") + except EOFError: + print("\nBye...") + sys.exit(0) + + if cmd.lower() == 'new': + + name = input("Where did you use this password for> ") + password = input("Enter the new password to save> ") + + if new(user_password, name, password) == 0: + + # Row added + print(f"[{GREEN_COLOR}+{NO_COLOR}] Successfully added...") + prompt(user_password) + + else: + + # ERROR + print( + f"[{RED_COLOR}-{NO_COLOR}] Error while writing the password..." + ) + prompt(user_password) + + elif cmd.lower() == 'delete': + + id_num = input("Which id? > ") + confirm = input("Are you sure [Y/n]> ") + + if confirm.lower() == 'y': + + if delete(id_num) == 0: + # Row deleted + print(f"[{GREEN_COLOR}+{NO_COLOR}] Successfully deleted...") + else: + # ERROR + print(f"[{RED_COLOR}-{NO_COLOR}] Error in deleting...") + + prompt(user_password) + + elif cmd.lower() == 'show': + + result = select_data(user_password) + + if result == -1: + # ERROR + print(f"[{RED_COLOR}-{NO_COLOR}] Error in selecting the data...") + else: + show_data(result) + + prompt(user_password) + + elif cmd.lower() == 'exit': + + print("Bye...") + sys.exit(0) + + else: + + print("Command not found...") + prompt(user_password) + + +def new(user_password, name, password, id_num=-1): + """ + This function used for inserting new row to the database. + It will return two values {0|-1}, + 0 means the row has inserted successfully, + -1 means there was an error. + parameters are (in sort) => + =================================== + user_password: The program password, + name: The tag of the new password, + password: The new password, + OPTIONAL id_num: Will be used for specific id number. + """ + + try: + with sqlite3.connect(FILENAME) as conn: + cursor = conn.cursor() + + if id_num == -1: + + # insert id auto-increment + cursor.execute( + """INSERT INTO passwords(name, password) VALUES ( + ?,? + );""", + [ + encrypt( + str(user_password).encode('utf-8'), + str(name).encode('utf-8') + ), + encrypt( + str(user_password).encode('utf-8'), + str(password).encode('utf-8') + ) + ] + ) + + else: + + # insert the given id number + cursor.execute( + """INSERT INTO passwords(id, name, password) VALUES ( + ?,?,? + );""", + [ + id_num, + encrypt( + str(user_password).encode('utf-8'), + str(name).encode('utf-8') + ), + encrypt( + str(user_password).encode('utf-8'), + str(password).encode('utf-8') + ) + ] + ) + + return 0 + except Exception: + return -1 + + +def delete(id_num): + """ + It gets an id number and will delete it from the database. + It will return two values {0|-1} + 0 means the row has deleted successfully, + -1 means there was an error. + """ + + try: + with sqlite3.connect(FILENAME) as conn: + cursor = conn.cursor() + cursor.execute( + "DELETE FROM passwords WHERE id = ? AND name != ?;", + [id_num, COOKIE] + ) + + return 0 + except Exception: + return -1 + + +def select_data(user_password): + """ + This function gets the program password (user_password) + and returns the passwords list. + returning -1 means there was an error + """ + + try: + with sqlite3.connect(FILENAME) as conn: + cursor = conn.cursor() + + # password => id, encrypted name and encrypted password + passwords = cursor.execute("SELECT * FROM passwords;").fetchall() + + # result => id, decrypted name and decrypted password + result = [] + + for (id_num, name, password) in passwords: + result.append( + ( + id_num, + decrypt( + str(user_password).encode('utf-8'), name + ).decode('utf-8'), + decrypt( + str(user_password).encode('utf-8'), password + ).decode('utf-8') + ) + ) + + return result + except Exception: + return -1 + + +def show_data(result): + """ + A function for printing the passwords. + It gets the password list. + """ + + # the length of result must be more than 1 + # because of the cookie row (0, ===PASSWORDS===, -) + if len(result) <= 1: + # Empty + print("\n\n====== Nothing ======\n\n") + else: + + print("\n==============================\n") + + for (id_num, name, password) in result: + if name != COOKIE: + print(f"({id_num}) {name} {GREEN_COLOR}{password}{NO_COLOR}") + + print("\n==============================\n") + + +def encrypt(key, source, encode=True): + """A function for encryption.""" + + # use SHA-256 over our key to get a proper-sized AES key + key = SHA256.new(key).digest() + + # generate iv + iv = Random.new().read(AES.block_size) + encryptor = AES.new(key, AES.MODE_CBC, iv) + + # calculate needed padding + padding = AES.block_size - len(source) % AES.block_size + + # Python 2.x: source += chr(padding) * padding + source += bytes([padding]) * padding + + # store the iv at the beginning and encrypt + data = iv + encryptor.encrypt(source) + return base64.b64encode(data).decode("utf-8") if encode else data + + +def decrypt(key, source, decode=True): + """A function for decrypting the encrypted datum.""" + + if decode: + source = base64.b64decode(source.encode("utf-8")) + + # use SHA-256 over our key to get a proper-sized AES key + key = SHA256.new(key).digest() + + # extract the IV from the beginning + IV = source[:AES.block_size] + decryptor = AES.new(key, AES.MODE_CBC, IV) + + # decrypt + data = decryptor.decrypt(source[AES.block_size:]) + + # pick the padding value from the end; Python 2.x: ord(data[-1]) + padding = data[-1] + + if data[-padding:] != bytes([padding]) * padding: + raise ValueError("Invalid padding...") + + # remove the padding + return data[:-padding] + + +def exit_program(sig, frame): + """For handling SIGINT signal.""" + + print("\nBye...") + sys.exit(0) + + +if __name__ == '__main__': + global args # The program arguments + + parser = argparse.ArgumentParser(description="Password Manager CLI") + # -p | --password PASSWORD + parser.add_argument( + '-p', + '--password', + metavar='password', + type=str, + default='', + help='the program password' + ) + args = parser.parse_args() + + # Handle SIGINT (same as ^C) signal + signal.signal(signal.SIGINT, exit_program) + + main() diff --git a/password_manager/requirements.txt b/password_manager/requirements.txt index 6c26d1860..5c6ac5857 100644 --- a/password_manager/requirements.txt +++ b/password_manager/requirements.txt @@ -1,5 +1,5 @@ -importlib-metadata==2.0.0 -mccabe==0.6.1 -pkg-resources==0.0.0 -pycrypto==2.6.1 -zipp==3.3.0 +importlib-metadata==2.0.0 +mccabe==0.6.1 +pkg-resources==0.0.0 +pycrypto==2.6.1 +zipp==3.3.0 diff --git a/pdf_editor/README.md b/pdf_editor/README.md index 000f97b04..b6852293c 100644 --- a/pdf_editor/README.md +++ b/pdf_editor/README.md @@ -1,42 +1,42 @@ -# pdf_editor - -## What it does - -Replaces text in PDF with another word. -Sequence: -Convert PDF to docx format -Search and replace word in file -Convert edited docx back to PDF - -Suitable for simple styled PDFs only. Style of edited PDF may vary from original depending on the original PDF template structure. - -## How to use - -### Setup modules - -Python and the following modules must be installed on the computer running this script. -Install the required modules by running this command in the directory of the requirements.txt file: -``` -pip install -r requirements.txt -``` - -##install libreoffice -``` -sudo add-apt-repository ppa:libreoffice/ppa -sudo apt-get update -sudo apt-get install libreoffice -``` - -### Run program - -Run using: -``` -python pdf_editor.py -``` - -You will be prompted for your settings. Example: -``` -Your settings (format: file_name.pdf text_to_replace replacement_text): file.pdf HelloWorld HelloUniverse -``` - +# pdf_editor + +## What it does + +Replaces text in PDF with another word. +Sequence: +Convert PDF to docx format +Search and replace word in file +Convert edited docx back to PDF + +Suitable for simple styled PDFs only. Style of edited PDF may vary from original depending on the original PDF template structure. + +## How to use + +### Setup modules + +Python and the following modules must be installed on the computer running this script. +Install the required modules by running this command in the directory of the requirements.txt file: +``` +pip install -r requirements.txt +``` + +##install libreoffice +``` +sudo add-apt-repository ppa:libreoffice/ppa +sudo apt-get update +sudo apt-get install libreoffice +``` + +### Run program + +Run using: +``` +python pdf_editor.py +``` + +You will be prompted for your settings. Example: +``` +Your settings (format: file_name.pdf text_to_replace replacement_text): file.pdf HelloWorld HelloUniverse +``` + The exported file "converted.pdf" is your edited pdf. \ No newline at end of file diff --git a/pdf_editor/pdf_editor.py b/pdf_editor/pdf_editor.py index 2cead0c35..099c2136b 100644 --- a/pdf_editor/pdf_editor.py +++ b/pdf_editor/pdf_editor.py @@ -1,49 +1,49 @@ -from docx import Document -from pdf2docx import parse -import subprocess -import os - - -def pdf_to_word(pdf_file): - - # convert to dpcx - word_file = 'word.docx' - parse(pdf_file, word_file) - - -def edit_word(find, replacement): - - # open docx file - word_file = Document('word.docx') - replace = {find: replacement} - - # scan file and replace text with new text - for x in replace: - for line in word_file.paragraphs: - if line.text.find(x) >= 0: - line.text = line.text.replace(x, replace[x]) - - # exported edited docx - word_file.save('converted.docx') - - -def word_to_pdf(): - - # export edited docx to pdf - subprocess.run(["libreoffice", "--headless", "--convert-to", "pdf", 'converted.docx']) - - # clean up files - if os.path.exists("word.docx"): - os.remove("word.docx") - if os.path.exists("converted.docx"): - os.remove("converted.docx") - - -if __name__ == "__main__": - - # get user input: pdf to edit, text to find, replacement text - file, find, replacement = input("Your settings (format: file_name.pdf text_to_replace replacement_text): ").split() - - pdf_to_word(file) - edit_word(find, replacement) - word_to_pdf() +from docx import Document +from pdf2docx import parse +import subprocess +import os + + +def pdf_to_word(pdf_file): + + # convert to dpcx + word_file = 'word.docx' + parse(pdf_file, word_file) + + +def edit_word(find, replacement): + + # open docx file + word_file = Document('word.docx') + replace = {find: replacement} + + # scan file and replace text with new text + for x in replace: + for line in word_file.paragraphs: + if line.text.find(x) >= 0: + line.text = line.text.replace(x, replace[x]) + + # exported edited docx + word_file.save('converted.docx') + + +def word_to_pdf(): + + # export edited docx to pdf + subprocess.run(["libreoffice", "--headless", "--convert-to", "pdf", 'converted.docx']) + + # clean up files + if os.path.exists("word.docx"): + os.remove("word.docx") + if os.path.exists("converted.docx"): + os.remove("converted.docx") + + +if __name__ == "__main__": + + # get user input: pdf to edit, text to find, replacement text + file, find, replacement = input("Your settings (format: file_name.pdf text_to_replace replacement_text): ").split() + + pdf_to_word(file) + edit_word(find, replacement) + word_to_pdf() diff --git a/pdf_editor/requirements.txt b/pdf_editor/requirements.txt index 091dc6577..f042809df 100644 --- a/pdf_editor/requirements.txt +++ b/pdf_editor/requirements.txt @@ -1,2 +1,2 @@ -pdf2docx==0.4.6 +pdf2docx==0.4.6 python_docx==0.8.10 \ No newline at end of file diff --git a/pdf_encrypt/README.md b/pdf_encrypt/README.md index a3f230b12..ae84c88b2 100644 --- a/pdf_encrypt/README.md +++ b/pdf_encrypt/README.md @@ -1,41 +1,41 @@ -# Using pdf_encryptor.py script - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## Steps to encrypt the PDF file : - -1. run the script `pdf_encrypt.py` and pass the path of the file as an argument. -Example : - ``` - python pdf_encryptor.py -e test_file.pdf - ``` - -2. Enter the password when prompted. - -3. The decrypted file will be saved as an `.aes` file in the working directory. - ``` - python pdf_encryptor.py -e test_file.pdf - - Will create: - test_file.pdf.aes - ``` - -## Steps to decrypt the encrypted PDF file : - -1. run the script `pdf_encryptor.py` and pass the path of the file as an argument. -Example : - ``` - python PdfDecrypt.py -d test_file.pdf.aes - ``` - -2. Enter the password when prompted. - -3. On __Successful decryption__ you will get the following prompt with the relative path to the decrypted file. - ``` - On successful decryption the file will be saved in the working directory, without the .aes extension. - ``` +# Using pdf_encryptor.py script + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## Steps to encrypt the PDF file : + +1. run the script `pdf_encrypt.py` and pass the path of the file as an argument. +Example : + ``` + python pdf_encryptor.py -e test_file.pdf + ``` + +2. Enter the password when prompted. + +3. The decrypted file will be saved as an `.aes` file in the working directory. + ``` + python pdf_encryptor.py -e test_file.pdf + + Will create: + test_file.pdf.aes + ``` + +## Steps to decrypt the encrypted PDF file : + +1. run the script `pdf_encryptor.py` and pass the path of the file as an argument. +Example : + ``` + python PdfDecrypt.py -d test_file.pdf.aes + ``` + +2. Enter the password when prompted. + +3. On __Successful decryption__ you will get the following prompt with the relative path to the decrypted file. + ``` + On successful decryption the file will be saved in the working directory, without the .aes extension. + ``` diff --git a/pdf_encrypt/makefile b/pdf_encrypt/makefile index 685dba5c9..b85d93685 100644 --- a/pdf_encrypt/makefile +++ b/pdf_encrypt/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ - fi +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ + fi diff --git a/pdf_encrypt/pdf_encryptor.py b/pdf_encrypt/pdf_encryptor.py index c53dd6ec1..f0f2715f0 100644 --- a/pdf_encrypt/pdf_encryptor.py +++ b/pdf_encrypt/pdf_encryptor.py @@ -1,70 +1,70 @@ -import argparse -import getpass -import pyAesCrypt -import os -import sys - - -BUFFERSIZE = 64 * 1024 - - -def parse_args(): - parser = argparse.ArgumentParser(description="Encrypt " - "and decrypt PDF files") - parser.add_argument('-e', '--encrypt', dest='encrypt', type=str, - nargs=1, metavar='filename', help='Encrypt') - parser.add_argument('-d', '--decrypt', dest='decrypt', type=str, - nargs=1, metavar='filename', help='Decrypt') - args = parser.parse_args() - - if len(sys.argv) == 1: - parser.print_help() - sys.exit() - else: - return args - - -def file_exist(filename): - """ - Check to see if the entered file exists or not. - """ - if not os.path.exists(filename): - print("Error: '{}' does not exist".format(filename)) - sys.exit() - - -def encrypt(filename, password): - """ - Function to generate the encrypted file. - """ - pyAesCrypt.encryptFile(filename, f"{filename}.aes", password, BUFFERSIZE) - - -def decrypt(filename, password): - """ - Function to decrypt the provided file. - """ - output = filename.replace(".aes", "") - try: - pyAesCrypt.decryptFile(filename, output, password, BUFFERSIZE) - except ValueError: - print("Wrong password (or file is corrupted).") - sys.exit() - - -if __name__ == '__main__': - args = parse_args() - if args.encrypt: - encrypt_file = args.encrypt[0] - file_exist(encrypt_file) - password = getpass.getpass("Please provide the password to " - "encrypt the file with: ") - encrypt(encrypt_file, password) - print("{} has been successfully encrypted.".format(encrypt_file)) - else: - decrypt_file = args.decrypt[0] - file_exist(decrypt_file) - password = getpass.getpass("Please provide the password to " - "decrypt the file with: ") - decrypt(decrypt_file, password) - print("{} has been successfully decrypted.".format(decrypt_file)) +import argparse +import getpass +import pyAesCrypt +import os +import sys + + +BUFFERSIZE = 64 * 1024 + + +def parse_args(): + parser = argparse.ArgumentParser(description="Encrypt " + "and decrypt PDF files") + parser.add_argument('-e', '--encrypt', dest='encrypt', type=str, + nargs=1, metavar='filename', help='Encrypt') + parser.add_argument('-d', '--decrypt', dest='decrypt', type=str, + nargs=1, metavar='filename', help='Decrypt') + args = parser.parse_args() + + if len(sys.argv) == 1: + parser.print_help() + sys.exit() + else: + return args + + +def file_exist(filename): + """ + Check to see if the entered file exists or not. + """ + if not os.path.exists(filename): + print("Error: '{}' does not exist".format(filename)) + sys.exit() + + +def encrypt(filename, password): + """ + Function to generate the encrypted file. + """ + pyAesCrypt.encryptFile(filename, f"{filename}.aes", password, BUFFERSIZE) + + +def decrypt(filename, password): + """ + Function to decrypt the provided file. + """ + output = filename.replace(".aes", "") + try: + pyAesCrypt.decryptFile(filename, output, password, BUFFERSIZE) + except ValueError: + print("Wrong password (or file is corrupted).") + sys.exit() + + +if __name__ == '__main__': + args = parse_args() + if args.encrypt: + encrypt_file = args.encrypt[0] + file_exist(encrypt_file) + password = getpass.getpass("Please provide the password to " + "encrypt the file with: ") + encrypt(encrypt_file, password) + print("{} has been successfully encrypted.".format(encrypt_file)) + else: + decrypt_file = args.decrypt[0] + file_exist(decrypt_file) + password = getpass.getpass("Please provide the password to " + "decrypt the file with: ") + decrypt(decrypt_file, password) + print("{} has been successfully decrypted.".format(decrypt_file)) diff --git a/pdf_encrypt/requirements.txt b/pdf_encrypt/requirements.txt index 995ff53f3..cd7f8163d 100644 --- a/pdf_encrypt/requirements.txt +++ b/pdf_encrypt/requirements.txt @@ -1,5 +1,5 @@ -cffi==1.14.3 -cryptography==3.1.1 -pyAesCrypt==0.4.3 -pycparser==2.20 -six==1.15.0 +cffi==1.14.3 +cryptography==3.1.1 +pyAesCrypt==0.4.3 +pycparser==2.20 +six==1.15.0 diff --git a/pdf_merger/README.md b/pdf_merger/README.md index a281095e8..7a9cf71c7 100644 --- a/pdf_merger/README.md +++ b/pdf_merger/README.md @@ -1,13 +1,13 @@ -# PDF Merger -![screenshot of the script running in the terminal](https://raw.githubusercontent.com/paulopacitti/Automation-scripts/main/pdf_merger/screenshots/1.png) -This is a simple _python3_ script to merge multiple `.pdf` files into one and only `.pdf` file :pray: - -## Install :arrow_down: -- Install the required dependencies running: `$ pip3 -r requirements.txt` and that's it! (_easy peasy_ :wink:) - -## Usage :play_or_pause_button: -- Run the script: `$ python3 pdf_merger.py` -- Follow each one of the steps and _voilΓ _ :sparkles: - -## Credits :heart: +# PDF Merger +![screenshot of the script running in the terminal](https://raw.githubusercontent.com/paulopacitti/Automation-scripts/main/pdf_merger/screenshots/1.png) +This is a simple _python3_ script to merge multiple `.pdf` files into one and only `.pdf` file :pray: + +## Install :arrow_down: +- Install the required dependencies running: `$ pip3 -r requirements.txt` and that's it! (_easy peasy_ :wink:) + +## Usage :play_or_pause_button: +- Run the script: `$ python3 pdf_merger.py` +- Follow each one of the steps and _voilΓ _ :sparkles: + +## Credits :heart: - Recipe made by _chef [@paulopacitti](https://github.com/paulopacitti)_ \ No newline at end of file diff --git a/pdf_merger/pdf_merger.py b/pdf_merger/pdf_merger.py index 9f16341fa..039684957 100644 --- a/pdf_merger/pdf_merger.py +++ b/pdf_merger/pdf_merger.py @@ -1,32 +1,32 @@ -import os -from PyPDF2 import PdfFileMerger - -print(""" -__________________ ___ ___ -| ___ \\ _ \\ ___| | \\/ | -| |_/ / | | | |_ | . . | ___ _ __ __ _ ___ _ __ -| __/| | | | _| | |\\/| |/ _ \\ '__/ _` |/ _ \\ '__| -| | | |/ /| | | | | | __/ | | (_| | __/ | -\\_| |___/ \\_| \\_| |_/\\___|_| \\__, |\\___|_| - __/ | - |___/ """) -print("πŸ“š Step 1: put the PDFs you want to merge in a folder!") -print("✏️ Step 2: name your files in the order you want to merge!\ - (like 'file1.pdf', 'file2.pdf'...)") - -path = os.path.abspath(input("πŸ“¬ Step 3: Type the path of the folder\ - containing the PDFs you want to merge (relative path): ")) -os.chdir(path) - -output_file = input("πŸ’Œ Step 4 (required): Name your output file: ") + ".pdf" - -pdfs_list = [file for file in os.listdir() if file.endswith(".pdf")] -pdfs_list = sorted(pdfs_list, key=lambda file: os.path.splitext(file)[0]) - -merger = PdfFileMerger() -for pdf in pdfs_list: - merger.append(pdf) - -merger.write(output_file) -merger.close() -print("✨ Done! Your PDFs has been merged! ✨") +import os +from PyPDF2 import PdfFileMerger + +print(""" +__________________ ___ ___ +| ___ \\ _ \\ ___| | \\/ | +| |_/ / | | | |_ | . . | ___ _ __ __ _ ___ _ __ +| __/| | | | _| | |\\/| |/ _ \\ '__/ _` |/ _ \\ '__| +| | | |/ /| | | | | | __/ | | (_| | __/ | +\\_| |___/ \\_| \\_| |_/\\___|_| \\__, |\\___|_| + __/ | + |___/ """) +print("πŸ“š Step 1: put the PDFs you want to merge in a folder!") +print("✏️ Step 2: name your files in the order you want to merge!\ + (like 'file1.pdf', 'file2.pdf'...)") + +path = os.path.abspath(input("πŸ“¬ Step 3: Type the path of the folder\ + containing the PDFs you want to merge (relative path): ")) +os.chdir(path) + +output_file = input("πŸ’Œ Step 4 (required): Name your output file: ") + ".pdf" + +pdfs_list = [file for file in os.listdir() if file.endswith(".pdf")] +pdfs_list = sorted(pdfs_list, key=lambda file: os.path.splitext(file)[0]) + +merger = PdfFileMerger() +for pdf in pdfs_list: + merger.append(pdf) + +merger.write(output_file) +merger.close() +print("✨ Done! Your PDFs has been merged! ✨") diff --git a/pdf_to_audio/README.md b/pdf_to_audio/README.md index 3e10ffe0e..c36913c15 100644 --- a/pdf_to_audio/README.md +++ b/pdf_to_audio/README.md @@ -1,14 +1,14 @@ -# PDF TO AUDIO -This is a simple pdf to Audio which speaks text from the pdf's aloud for you. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## How to use : - Run the program and a dialog box will appear. Just select the .pdf file you want to convert to audio. - Then It will provide you with the choice to dictate the whole file and then save the audio file or directly save it without dictation +# PDF TO AUDIO +This is a simple pdf to Audio which speaks text from the pdf's aloud for you. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## How to use : + Run the program and a dialog box will appear. Just select the .pdf file you want to convert to audio. + Then It will provide you with the choice to dictate the whole file and then save the audio file or directly save it without dictation Provide the name of the audio file. Then .mp3 file will be saved in the same directory. \ No newline at end of file diff --git a/pdf_to_audio/makefile b/pdf_to_audio/makefile index e78e53c81..7aafa604a 100644 --- a/pdf_to_audio/makefile +++ b/pdf_to_audio/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/pdf_to_audio/pdf_to_audio.py b/pdf_to_audio/pdf_to_audio.py index 44aaf4aa4..50730d82b 100644 --- a/pdf_to_audio/pdf_to_audio.py +++ b/pdf_to_audio/pdf_to_audio.py @@ -1,27 +1,27 @@ -import pyttsx3 -import PyPDF2 -from tkinter.filedialog import askopenfilename -from tkinter import Tk -from gtts import gTTS -Tk().withdraw() -filelocation = askopenfilename() # To select pdf files - - -pdf_file = open(filelocation, 'rb') -pdfReader = PyPDF2.PdfFileReader(pdf_file) -speak = pyttsx3.init() -pages = pdfReader.numPages -complete_pdf = "" -choice = input("Press 1 to dictate or anything else to skip dictation ") -for i in range(0, pages): - from_page = pdfReader.getPage(i) - text = from_page.extractText() - if choice == "1": - speak.say("Page Number:" + str(i + 1)) - speak.say(text) - complete_pdf += text -speak.runAndWait() -final_file = gTTS(text=complete_pdf, lang='en') # store file in variable -file_name = input("Name of the MP3 file: ") -final_file.save(file_name + ".mp3") # Saving audio file -print("Conversion is Complete") +import pyttsx3 +import PyPDF2 +from tkinter.filedialog import askopenfilename +from tkinter import Tk +from gtts import gTTS +Tk().withdraw() +filelocation = askopenfilename() # To select pdf files + + +pdf_file = open(filelocation, 'rb') +pdfReader = PyPDF2.PdfFileReader(pdf_file) +speak = pyttsx3.init() +pages = pdfReader.numPages +complete_pdf = "" +choice = input("Press 1 to dictate or anything else to skip dictation ") +for i in range(0, pages): + from_page = pdfReader.getPage(i) + text = from_page.extractText() + if choice == "1": + speak.say("Page Number:" + str(i + 1)) + speak.say(text) + complete_pdf += text +speak.runAndWait() +final_file = gTTS(text=complete_pdf, lang='en') # store file in variable +file_name = input("Name of the MP3 file: ") +final_file.save(file_name + ".mp3") # Saving audio file +print("Conversion is Complete") diff --git a/pdf_to_audio/requirements.txt b/pdf_to_audio/requirements.txt index c4c59b023..7d46b5aa9 100644 --- a/pdf_to_audio/requirements.txt +++ b/pdf_to_audio/requirements.txt @@ -1,3 +1,3 @@ -pyttsx3 -PyPDF2 +pyttsx3 +PyPDF2 gtts \ No newline at end of file diff --git a/pdf_toimg/main_code.py b/pdf_toimg/main_code.py index fa763a1ab..b6b58204b 100644 --- a/pdf_toimg/main_code.py +++ b/pdf_toimg/main_code.py @@ -1,29 +1,29 @@ -import os -import sys -from PyPDF2 import PdfFileMerger -from pdf2image import convert_from_path - -sys.path.insert(1, '''B:/Production_Programs/Github/ - Automation-scripts/Pdf_to_image/sample_files''') - -fileName = "myfile.pdf" -if os.path.exists(fileName): - os.remove(fileName) - -# merge pdfs into one -x = [a for a in os.listdir() if a.endswith(".pdf")] -merger = PdfFileMerger() -for pdf in x: - merger.append(open(pdf, 'rb')) - -with open(fileName, "wb") as fout: - merger.write(fout) - -# convert merged pdf to png files -images = convert_from_path(fileName) - -for i, image in enumerate(images): - fname = 'image' + str(i) + '.png' - image.save(fname, "PNG") - -print("all file converted") +import os +import sys +from PyPDF2 import PdfFileMerger +from pdf2image import convert_from_path + +sys.path.insert(1, '''B:/Production_Programs/Github/ + Automation-scripts/Pdf_to_image/sample_files''') + +fileName = "myfile.pdf" +if os.path.exists(fileName): + os.remove(fileName) + +# merge pdfs into one +x = [a for a in os.listdir() if a.endswith(".pdf")] +merger = PdfFileMerger() +for pdf in x: + merger.append(open(pdf, 'rb')) + +with open(fileName, "wb") as fout: + merger.write(fout) + +# convert merged pdf to png files +images = convert_from_path(fileName) + +for i, image in enumerate(images): + fname = 'image' + str(i) + '.png' + image.save(fname, "PNG") + +print("all file converted") diff --git a/pdf_toimg/requirements.txt b/pdf_toimg/requirements.txt index 11954b953..0bd006a0b 100644 --- a/pdf_toimg/requirements.txt +++ b/pdf_toimg/requirements.txt @@ -1,4 +1,4 @@ -pillow -pypdf2 -pdf2image +pillow +pypdf2 +pdf2image poppler \ No newline at end of file diff --git a/pdf_toimg/sample_files/sample.pdf b/pdf_toimg/sample_files/sample.pdf index c0e31a076..dbf091df9 100644 Binary files a/pdf_toimg/sample_files/sample.pdf and b/pdf_toimg/sample_files/sample.pdf differ diff --git a/pdf_watermarkadder/README.md b/pdf_watermarkadder/README.md index 936d069ba..da6236c61 100644 --- a/pdf_watermarkadder/README.md +++ b/pdf_watermarkadder/README.md @@ -1,15 +1,15 @@ -# PDF Watermaker - -### Getting started: -- To begin with you will have to download the required modules. You can do this by doing: - `pip install -r requirements.txt` or `pip3 install -r requirements.txt` -- After that make sure to keep the pdf you want to add the watermark to, is in the same directory as the python script. -- After executing the program it will ask you for: - -- The Text you want to use as a watermark - -- The name of the pdf file you want to add the watermark to -- The script will save the final file by the name finalDraft.pdf - -- Example result : - -![Img](./images/img1.png =250x) ![Img](./images/img2.png =250x) - +# PDF Watermaker + +### Getting started: +- To begin with you will have to download the required modules. You can do this by doing: + `pip install -r requirements.txt` or `pip3 install -r requirements.txt` +- After that make sure to keep the pdf you want to add the watermark to, is in the same directory as the python script. +- After executing the program it will ask you for: + -- The Text you want to use as a watermark + -- The name of the pdf file you want to add the watermark to +- The script will save the final file by the name finalDraft.pdf + +- Example result : + +![Img](./images/img1.png =250x) ![Img](./images/img2.png =250x) + diff --git a/pdf_watermarkadder/main.py b/pdf_watermarkadder/main.py index d6d9b0a28..71df27927 100644 --- a/pdf_watermarkadder/main.py +++ b/pdf_watermarkadder/main.py @@ -1,44 +1,44 @@ -from reportlab.pdfgen import canvas -from reportlab.lib.units import inch -from reportlab.lib import colors -from reportlab.lib.pagesizes import A4 -from PyPDF2 import PdfFileReader, PdfFileWriter - - -print("Enter file names with its extenstion!") - - -def makeWatermark(): - text = input("Enter the watermark text here:") - pdf6 = canvas.Canvas("watermark.pdf", pagesize=A4) - pdf6.translate(inch, inch) - pdf6.setFillColor(colors.grey, alpha=0.6) - pdf6.setFont("Helvetica", 50) - pdf6.rotate(45) - pdf6.drawCentredString(400, 100, text) - pdf6.save() - - -def makepdf(): - pdf_file = input("PDF file: ") - watermark = 'watermark.pdf' - merged = "finalDraft.pdf" - with open(pdf_file, "rb") as input_file,\ - open(watermark, "rb") as watermark_file: - input_pdf = PdfFileReader(input_file) - watermark_pdf = PdfFileReader(watermark_file) - watermark_page = watermark_pdf.getPage(0) - - output = PdfFileWriter() - - for i in range(input_pdf.getNumPages()): - pdf_page = input_pdf.getPage(i) - pdf_page.mergePage(watermark_page) - output.addPage(pdf_page) - - with open(merged, "wb") as merged_file: - output.write(merged_file) - - -makeWatermark() -makepdf() +from reportlab.pdfgen import canvas +from reportlab.lib.units import inch +from reportlab.lib import colors +from reportlab.lib.pagesizes import A4 +from PyPDF2 import PdfFileReader, PdfFileWriter + + +print("Enter file names with its extenstion!") + + +def makeWatermark(): + text = input("Enter the watermark text here:") + pdf6 = canvas.Canvas("watermark.pdf", pagesize=A4) + pdf6.translate(inch, inch) + pdf6.setFillColor(colors.grey, alpha=0.6) + pdf6.setFont("Helvetica", 50) + pdf6.rotate(45) + pdf6.drawCentredString(400, 100, text) + pdf6.save() + + +def makepdf(): + pdf_file = input("PDF file: ") + watermark = 'watermark.pdf' + merged = "finalDraft.pdf" + with open(pdf_file, "rb") as input_file,\ + open(watermark, "rb") as watermark_file: + input_pdf = PdfFileReader(input_file) + watermark_pdf = PdfFileReader(watermark_file) + watermark_page = watermark_pdf.getPage(0) + + output = PdfFileWriter() + + for i in range(input_pdf.getNumPages()): + pdf_page = input_pdf.getPage(i) + pdf_page.mergePage(watermark_page) + output.addPage(pdf_page) + + with open(merged, "wb") as merged_file: + output.write(merged_file) + + +makeWatermark() +makepdf() diff --git a/pdf_watermarkadder/requirements.txt b/pdf_watermarkadder/requirements.txt index 1991006b3..54af5ff92 100644 --- a/pdf_watermarkadder/requirements.txt +++ b/pdf_watermarkadder/requirements.txt @@ -1,2 +1,2 @@ -PyPDF2==1.26.0 -reportlab==3.5.53 +PyPDF2==1.26.0 +reportlab==3.5.53 diff --git a/prescription_generator/Prescription.pdf b/prescription_generator/Prescription.pdf new file mode 100644 index 000000000..e1d46a89b Binary files /dev/null and b/prescription_generator/Prescription.pdf differ diff --git a/prescription_generator/README.md b/prescription_generator/README.md new file mode 100644 index 000000000..d95954026 --- /dev/null +++ b/prescription_generator/README.md @@ -0,0 +1,30 @@ +# Automated Voice based Prescription Generator + +## Use Case: +Generates Prescriptions in the form of PDF Files by recognizing the voice from doctors. This process will remove a lot of manual works and human errors as well as useful for the cases where doctor can't prescribe medicines physically. + +## Features: +* Input information through voice. +* Control instructions through voice inputs. +* Generates simply formatted PDF as Output. +* Auto Noice Adjustment. +* Exceptions Handling. + +## Technologies used: +* Python +* Speech Recognition +* Text to PDF Convertion + +## Steps to run locally: +
+ +1. clone the repository +2. cd automated_voice_prescription_generator +3. pip install -r requirements.txt +4. python main.py +5. Terminate the code anytime by saying 'exit' +## Errors: +* Incase you face issues related to **PyAudio**, run the below commands: + + pip install pipwin + pipwin install pyaudio diff --git a/prescription_generator/helper/__init__.py b/prescription_generator/helper/__init__.py new file mode 100644 index 000000000..31d666954 --- /dev/null +++ b/prescription_generator/helper/__init__.py @@ -0,0 +1,2 @@ +# from .pdf_operations import save_pdf +# from .speech import speech_rec_for_windows, speech_rec_for_linux diff --git a/prescription_generator/helper/pdf_operations.py b/prescription_generator/helper/pdf_operations.py new file mode 100644 index 000000000..a195cfae9 --- /dev/null +++ b/prescription_generator/helper/pdf_operations.py @@ -0,0 +1,57 @@ +from fpdf import FPDF + + +class PDF(FPDF): + def footer(self): + # Position at 1.5 cm from bottom + self.set_y(-15) + # Arial italic 8 + self.set_font('Arial', 'I', 8) + # Text color in gray + self.set_text_color(128) + # Page number + self.cell(0, 10, 'Page ' + str(self.page_no()), 0, 0, 'C') + + +def save_pdf(medicines): + pdf = PDF() + + # Add a page + pdf.add_page() + + # setting style and size of font for the pdf + pdf.set_font("Arial", size=12) + pdf.cell( + 200, 10, + txt="Generated Prscription", + ln=1, align='C' + ) + + for medic in medicines: + if ('Medicine Name' in medicines[medic]): + # create a cell + pdf.cell( + 200, 10, + ln=1, align='C', + txt=medic + ) + pdf.cell( + 200, 10, + ln=2, + txt="Medicine Name: " + medicines[medic]["Medicine Name"], + ) + if "Instruction" in medicines[medic]: + pdf.cell( + 200, 10, + ln=2, + txt="Instructions: " + medicines[medic]["Instruction"] + ) + else: + pdf.cell( + 200, 10, + ln=2, + txt="Instructions*: No Instructions given" + ) + + # save the pdf with name .pdf + pdf.output("Prescription.pdf") diff --git a/prescription_generator/helper/speech.py b/prescription_generator/helper/speech.py new file mode 100644 index 000000000..201eedb8e --- /dev/null +++ b/prescription_generator/helper/speech.py @@ -0,0 +1,139 @@ +import speech_recognition as sr + + +def speech_rec_for_linux(): + import espeak + espeak.init() + speaker = espeak.Espeak() + # import pyttsx3 + # speaker = pyttsx3.init() + + r = sr.Recognizer() + text = "" + count = 0 + medicines = {} + + with sr.Microphone() as source: + while(True): + medicine_dict = {} + count += 1 + + print("Medicine-" + str(count) + " Information") + + print("Adjusting noise ") + r.adjust_for_ambient_noise(source, duration=1) + + print("Medicine Name:") + speaker.say("Medicine name") + # speaker.rate = 300 + + recorded_audio = r.listen(source, timeout=6) + print("Done") + + try: + text = r.recognize_google( + recorded_audio, + language="en-US" + ) + if 'exit' in str(text).lower(): + print("Thanks for using our service!") + break + + medicine_dict["Medicine Name"] = str(text) + print("Decoded Text : {}".format(text)) + + except Exception as e: + print(e) + + print("Adjusting noise ") + r.adjust_for_ambient_noise(source, duration=1) + + print("Medicine Instruction:") + speaker.say("Medicine Instruction") + + recorded_audio = r.listen(source, timeout=6) + print("Done") + + try: + text = r.recognize_google( + recorded_audio, + language="en-US" + ) + medicine_dict["Instruction"] = str(text) + print("Decoded Text : {}".format(text)) + + except Exception as e: + print(e) + + medicines["Medicine No. " + str(count)] = medicine_dict + + return medicines + + +def speech_rec_for_windows(): + import pyttsx3 + speaker = pyttsx3.init() + # from win32com.client import Dispatch + # speak = Dispatch("SAPI.SpVoice").Speak + + r = sr.Recognizer() + text = "" + count = 0 + medicines = {} + + with sr.Microphone() as source: + while(True): + medicine_dict = {} + count += 1 + + print("Medicine-" + str(count) + " Information") + + print("Adjusting noise ") + r.adjust_for_ambient_noise(source, duration=1) + + print("Medicine Name:") + speaker.say("Medicine name") + speaker.runAndWait() + + recorded_audio = r.listen(source, timeout=6) + print("Done") + + try: + text = r.recognize_google( + recorded_audio, + language="en-US" + ) + if 'exit' in str(text).lower(): + print("Thanks for using our service!") + break + + medicine_dict["Medicine Name"] = str(text) + print("Decoded Text : {}".format(text)) + + except Exception as e: + print("Exception", e) + + print("Adjusting noise ") + r.adjust_for_ambient_noise(source, duration=1) + + print("Medicine Instruction:") + speaker.say("Medicine Instruction") + speaker.runAndWait() + + recorded_audio = r.listen(source, timeout=6) + print("Done") + + try: + text = r.recognize_google( + recorded_audio, + language="en-US" + ) + medicine_dict["Instruction"] = str(text) + print("Decoded Text : {}".format(text)) + + except Exception as e: + print("Exception", e) + + medicines["Medicine No. " + str(count)] = medicine_dict + + return medicines diff --git a/prescription_generator/main.py b/prescription_generator/main.py new file mode 100644 index 000000000..42935d66d --- /dev/null +++ b/prescription_generator/main.py @@ -0,0 +1,18 @@ +import sys +from helper.pdf_operations import save_pdf +from helper.speech import speech_rec_for_windows, speech_rec_for_linux + + +def start_app(): + if sys.platform.startswith('linux'): + medicines = speech_rec_for_linux() + + elif sys.platform.startswith('win32'): + medicines = speech_rec_for_windows() + + print(medicines) + save_pdf(medicines) + + +if __name__ == '__main__': + start_app() diff --git a/prescription_generator/requirements.txt b/prescription_generator/requirements.txt new file mode 100644 index 000000000..e24abac12 --- /dev/null +++ b/prescription_generator/requirements.txt @@ -0,0 +1,23 @@ +beautifulsoup4==4.9.3 +certifi==2020.12.5 +chardet==4.0.0 +docopt==0.6.2 +fpdf==1.7.2 +idna==2.10 +Js2Py==0.71 +packaging==20.9 +pipwin==0.5.1 +PyAudio==0.2.11 +pydub==0.25.1 +pyjsparser==2.7.1 +pyparsing==2.4.7 +PyPrind==2.11.2 +pySmartDL==1.3.4 +python-espeak==0.6.3 +pytz==2021.1 +requests==2.25.1 +six==1.15.0 +soupsieve==2.2.1 +SpeechRecognition==3.8.1 +tzlocal==2.1 +urllib3==1.26.4 diff --git a/programming_quoter/requirements.txt b/programming_quoter/requirements.txt index cb5029afa..4412fe810 100644 --- a/programming_quoter/requirements.txt +++ b/programming_quoter/requirements.txt @@ -1,3 +1,3 @@ -pywin32==228 -pypiwin32==223 -win10toast==0.9 +pywin32==228 +pypiwin32==223 +win10toast==0.9 diff --git a/qrcode_scanner/makefile b/qrcode_scanner/makefile index e78e53c81..7aafa604a 100644 --- a/qrcode_scanner/makefile +++ b/qrcode_scanner/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/quick_painter/README.md b/quick_painter/README.md index 5fdd4cd77..c69955651 100644 --- a/quick_painter/README.md +++ b/quick_painter/README.md @@ -1,17 +1,17 @@ -Basically open the script and draw whatever you like and save it as a PNG or JPG file! - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -Left Mouse Button to Draw -Right Mouse Button to Erase - -Click on the "Choose Color" button to choose color -Click on the "Save" button to save your sketch into a PNG or a JPG file -Click on the "Clear" button to clear the canvas! - +Basically open the script and draw whatever you like and save it as a PNG or JPG file! + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +Left Mouse Button to Draw +Right Mouse Button to Erase + +Click on the "Choose Color" button to choose color +Click on the "Save" button to save your sketch into a PNG or a JPG file +Click on the "Clear" button to clear the canvas! + That's it. Have Fun! \ No newline at end of file diff --git a/quick_painter/main.py b/quick_painter/main.py index d745a522b..4782419b4 100644 --- a/quick_painter/main.py +++ b/quick_painter/main.py @@ -1,87 +1,87 @@ -from tkinter import Tk, Button, Canvas -from tkinter import colorchooser -from tkinter import filedialog -from PIL import Image, ImageDraw - -width = 1280 -height = 720 - -background = "#2d2d2d" - -image = Image.new("RGB", (width, height), background) -draw = ImageDraw.Draw(image) - -window = Tk() -window.title("QuickPaint") -window.geometry(f"{width}x{height}") - -color = "#ffffff" - - -def ButtonColor(): - global color - colortemp = (colorchooser.askcolor(title="Choose Color"))[1] - color = colortemp - - -buttonColor = Button(window, text="Choose Color", command=ButtonColor, width=10) -buttonColor.pack(side="top", fill="y", expand=True, padx=0, pady=0) - - -def ButtonSave(): - files = [("PNG", "*.png"), ("JPG", "*.jpg")] - file_ = filedialog.asksaveasfile(filetypes=files, defaultextension=".png") - print(file_) - image.save(file_.name) - - -buttonSave = Button(window, text="Save", command=ButtonSave, width=10) -buttonSave.pack(side="top", fill="y", expand=True, padx=0, pady=0) - - -def ButtonClear(): - canvas.delete("all") - draw.rectangle([(0, 0), (width, height)], fill=background) - - -buttonClear = Button(window, text="Clear", command=ButtonClear, width=10) -buttonClear.pack(side="top", fill="y", expand=True, padx=0, pady=0) -canvas = Canvas(window, bg=background, height=720, width=1000) -canvas.pack() - -cursor_ = None - - -def cursor(event): - global cursor_ - if cursor_ not in canvas.find_all(): - cursor_ = canvas.create_oval(event.x - 10, event.y - 10, event.x + 10, event.y + 10, width=0, fill='cyan') - canvas.coords(cursor_, event.x - 10, event.y - 10, event.x + 10, event.y + 10) - canvas.update_idletasks() - - -def paint(event): - canvas.coords(cursor_, event.x - 10, event.y - 10, event.x + 10, event.y + 10) - - x1, y1 = (event.x - 10), (event.y - 10) - x2, y2 = (event.x + 10), (event.y + 10) - canvas.create_oval(x1, y1, x2, y2, width=0, fill=color) - draw.ellipse([(event.x - 10, event.y - 10), (event.x + 10, event.y + 10)], fill=color) - canvas.update_idletasks() - - -def erase(event): - canvas.coords(cursor_, event.x - 10, event.y - 10, event.x + 10, event.y + 10) - - item = canvas.find_closest(event.x, event.y) - coords = canvas.coords(item) - if (abs(event.x - (coords[0] + 10)) < 35 and abs(event.y - (coords[1] + 10)) < 35): - canvas.delete(item) - draw.ellipse([(coords[0], coords[1]), (coords[2], coords[3])], fill=background) - - -canvas.bind("", paint) -canvas.bind("", erase) -canvas.bind("", cursor) - -window.mainloop() +from tkinter import Tk, Button, Canvas +from tkinter import colorchooser +from tkinter import filedialog +from PIL import Image, ImageDraw + +width = 1280 +height = 720 + +background = "#2d2d2d" + +image = Image.new("RGB", (width, height), background) +draw = ImageDraw.Draw(image) + +window = Tk() +window.title("QuickPaint") +window.geometry(f"{width}x{height}") + +color = "#ffffff" + + +def ButtonColor(): + global color + colortemp = (colorchooser.askcolor(title="Choose Color"))[1] + color = colortemp + + +buttonColor = Button(window, text="Choose Color", command=ButtonColor, width=10) +buttonColor.pack(side="top", fill="y", expand=True, padx=0, pady=0) + + +def ButtonSave(): + files = [("PNG", "*.png"), ("JPG", "*.jpg")] + file_ = filedialog.asksaveasfile(filetypes=files, defaultextension=".png") + print(file_) + image.save(file_.name) + + +buttonSave = Button(window, text="Save", command=ButtonSave, width=10) +buttonSave.pack(side="top", fill="y", expand=True, padx=0, pady=0) + + +def ButtonClear(): + canvas.delete("all") + draw.rectangle([(0, 0), (width, height)], fill=background) + + +buttonClear = Button(window, text="Clear", command=ButtonClear, width=10) +buttonClear.pack(side="top", fill="y", expand=True, padx=0, pady=0) +canvas = Canvas(window, bg=background, height=720, width=1000) +canvas.pack() + +cursor_ = None + + +def cursor(event): + global cursor_ + if cursor_ not in canvas.find_all(): + cursor_ = canvas.create_oval(event.x - 10, event.y - 10, event.x + 10, event.y + 10, width=0, fill='cyan') + canvas.coords(cursor_, event.x - 10, event.y - 10, event.x + 10, event.y + 10) + canvas.update_idletasks() + + +def paint(event): + canvas.coords(cursor_, event.x - 10, event.y - 10, event.x + 10, event.y + 10) + + x1, y1 = (event.x - 10), (event.y - 10) + x2, y2 = (event.x + 10), (event.y + 10) + canvas.create_oval(x1, y1, x2, y2, width=0, fill=color) + draw.ellipse([(event.x - 10, event.y - 10), (event.x + 10, event.y + 10)], fill=color) + canvas.update_idletasks() + + +def erase(event): + canvas.coords(cursor_, event.x - 10, event.y - 10, event.x + 10, event.y + 10) + + item = canvas.find_closest(event.x, event.y) + coords = canvas.coords(item) + if (abs(event.x - (coords[0] + 10)) < 35 and abs(event.y - (coords[1] + 10)) < 35): + canvas.delete(item) + draw.ellipse([(coords[0], coords[1]), (coords[2], coords[3])], fill=background) + + +canvas.bind("", paint) +canvas.bind("", erase) +canvas.bind("", cursor) + +window.mainloop() diff --git a/quick_painter/makefile b/quick_painter/makefile index e78e53c81..7aafa604a 100644 --- a/quick_painter/makefile +++ b/quick_painter/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/random_wallpaper/README.md b/random_wallpaper/README.md index a732518c7..af1cb3502 100644 --- a/random_wallpaper/README.md +++ b/random_wallpaper/README.md @@ -1,17 +1,17 @@ -# Random wallpaper - -Basic script for changing wallpaper on Windows. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## No prerequisite - -## How to use - -* In the script, change the variable `PATH` so that it points to your wallpaper file. +# Random wallpaper + +Basic script for changing wallpaper on Windows. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## No prerequisite + +## How to use + +* In the script, change the variable `PATH` so that it points to your wallpaper file. * `py random_wallpaper.py` and it will change your wallpaper \ No newline at end of file diff --git a/random_wallpaper/makefile b/random_wallpaper/makefile index e78e53c81..7aafa604a 100644 --- a/random_wallpaper/makefile +++ b/random_wallpaper/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/random_wallpaper/random_wallpaper.py b/random_wallpaper/random_wallpaper.py index d5b788654..07728456e 100644 --- a/random_wallpaper/random_wallpaper.py +++ b/random_wallpaper/random_wallpaper.py @@ -1,18 +1,18 @@ -import ctypes -import random -import os - -PATH = "C:\\Users\\your\\path\\to\\wallpaper" -SPI_SETDESKWALLPAPER = 20 # 0x0014 -SPIF_SENDCHANGE = 3 # 0x0003 - -pic = random.choice(os.listdir(PATH)) - -new_wallpaper = PATH + "\\" + pic - -ctypes.windll.user32.SystemParametersInfoW( - SPI_SETDESKWALLPAPER, - 0, - new_wallpaper, - SPIF_SENDCHANGE -) +import ctypes +import random +import os + +PATH = "C:\\Users\\your\\path\\to\\wallpaper" +SPI_SETDESKWALLPAPER = 20 # 0x0014 +SPIF_SENDCHANGE = 3 # 0x0003 + +pic = random.choice(os.listdir(PATH)) + +new_wallpaper = PATH + "\\" + pic + +ctypes.windll.user32.SystemParametersInfoW( + SPI_SETDESKWALLPAPER, + 0, + new_wallpaper, + SPIF_SENDCHANGE +) diff --git a/rpyaudio_recorder/README.md b/rpyaudio_recorder/README.md index 72e3707c4..6c278f7ab 100644 --- a/rpyaudio_recorder/README.md +++ b/rpyaudio_recorder/README.md @@ -1,51 +1,51 @@ - -# Non blocking Audio Recorder for Raspberry PI ----- -## Features - -- Record audio using a push button - -## Dependencies - -Follow following steps to install dependencies (Linux) - -```bash -python3 -m pip install -r requirements.txt #To install all dependencies stated in requirements.txt file -``` - -## Usage - -This directory contains a python program to record audio clips in wav format using a push button. Opertion is as follows : - -1. Button Pressed --> Start Recording -1. Button Hold --> Record -1. Button Depressed --> Stop Recording and save audio file (Locally) - - -## Schematic - -![Schematic Diagram](schematic.png?raw=true "Schematic Diagram") - - -##### You can run the script by typing : - -```bash -python3 non_blocking_audio_recorder.py -``` - - -##### Sample Output - -###### Here, I am using Raspberry PI 3B+ and a simple Push Button connected to GPIO 17 and a GROUND of PI as shown in Schematic above - -``` -Audio Directory is Unavailable, so that's why creating one -Button is pressed -Starting Recording -print("In recordTag") -Saving with timestamp audio recording to loaction : /home/atom/Documents/projects/Automation-scripts/non_blocking_audio_recorder_raspberrypi/Audio/1603126373.wav -Recording Started -Button is depressed,Turning off recording -Recording Finished -^C Keyboard Interrupt caught -> Exiting + +# Non blocking Audio Recorder for Raspberry PI +---- +## Features + +- Record audio using a push button + +## Dependencies + +Follow following steps to install dependencies (Linux) + +```bash +python3 -m pip install -r requirements.txt #To install all dependencies stated in requirements.txt file +``` + +## Usage + +This directory contains a python program to record audio clips in wav format using a push button. Opertion is as follows : + +1. Button Pressed --> Start Recording +1. Button Hold --> Record +1. Button Depressed --> Stop Recording and save audio file (Locally) + + +## Schematic + +![Schematic Diagram](schematic.png?raw=true "Schematic Diagram") + + +##### You can run the script by typing : + +```bash +python3 non_blocking_audio_recorder.py +``` + + +##### Sample Output + +###### Here, I am using Raspberry PI 3B+ and a simple Push Button connected to GPIO 17 and a GROUND of PI as shown in Schematic above + +``` +Audio Directory is Unavailable, so that's why creating one +Button is pressed +Starting Recording +print("In recordTag") +Saving with timestamp audio recording to loaction : /home/atom/Documents/projects/Automation-scripts/non_blocking_audio_recorder_raspberrypi/Audio/1603126373.wav +Recording Started +Button is depressed,Turning off recording +Recording Finished +^C Keyboard Interrupt caught -> Exiting ``` \ No newline at end of file diff --git a/rpyaudio_recorder/non_blocking_audio_recorder.py b/rpyaudio_recorder/non_blocking_audio_recorder.py index 0cf11c0c6..27fb2cf75 100644 --- a/rpyaudio_recorder/non_blocking_audio_recorder.py +++ b/rpyaudio_recorder/non_blocking_audio_recorder.py @@ -1,87 +1,87 @@ -from recorder import Recorder # custom recorder script -from gpiozero import Button # for button interface -from datetime import datetime -import signal # Using this library to catch keyboard interrupts -import os -import sys - -ROOT_PATH = os.path.realpath(os.path.join(__file__, '..')) - - -def signal_handler(signal, frame): - print(" Keyboard Interrupt caught -> Exiting") - sys.exit(0) - - -signal.signal(signal.SIGINT, signal_handler) - - -class ButtonRecorder(): - def __init__(self): - """ - Initialize button and recorder - * Connect a push button to GPIO 17 and GROUND - * OPeration -> - Button Pressed -> Start Recording - Button Hold -> Record - Button Depressed -> Stop Recording and save the file with wave format - """ - self.button = Button(17, pull_up=True) - - # For mono channels = 1, for stereo channels = 2 - # Optional arguments rate=16000 (Bit Rate), frames_per_buffer=1024*4 (Buffer Size) - self.recorderHandler = Recorder(channels=1) - self.recfile = None - - # path where audio files will be saved - if os.path.isdir(ROOT_PATH + "/Audio"): - print("Audio Directory is Available") - else: - print("Audio Directory is Unavailable, so that's why creating one") - os.makedirs(ROOT_PATH + "/Audio") - - self.path = ROOT_PATH + "/Audio/" - self.button.when_pressed = self.pressed - - def timeStamp(self): - """ - Generate time stamp - """ - now = datetime.now() - timestamp1 = int(datetime.timestamp(now)) - return str(timestamp1) - - def pressed(self): - print("Button is pressed") - recordingFileName = self.timeStamp() - recordingFileNameWithLocation = self.path + recordingFileName + ".wav" - print("Starting Recording") - self.startRecording(recordingFileNameWithLocation) - - def startRecording(self, name): - """ - Summary: records audio clip and saves it to appropiate location - - Parameters - ---------- - tag : recordingFileName - - TYPE: str - Description : - """ - print("In recordTag") - self.button.when_released = self.released - print("Saving with timestamp audio recording to loaction : {}".format(name)) - self.recfile = self.recorderHandler.open(name, 'wb') - self.recfile.start_recording() - print("Recording Started") - - def released(self): - """ - Summary: On button released save recorded Clip - """ - print("Button is depressed,Turning off recording") - self.recfile.stop_recording() - self.recfile.close() - print("Recording Finished") - self.button.when_released = None # Make button release to none +from recorder import Recorder # custom recorder script +from gpiozero import Button # for button interface +from datetime import datetime +import signal # Using this library to catch keyboard interrupts +import os +import sys + +ROOT_PATH = os.path.realpath(os.path.join(__file__, '..')) + + +def signal_handler(signal, frame): + print(" Keyboard Interrupt caught -> Exiting") + sys.exit(0) + + +signal.signal(signal.SIGINT, signal_handler) + + +class ButtonRecorder(): + def __init__(self): + """ + Initialize button and recorder + * Connect a push button to GPIO 17 and GROUND + * OPeration -> + Button Pressed -> Start Recording + Button Hold -> Record + Button Depressed -> Stop Recording and save the file with wave format + """ + self.button = Button(17, pull_up=True) + + # For mono channels = 1, for stereo channels = 2 + # Optional arguments rate=16000 (Bit Rate), frames_per_buffer=1024*4 (Buffer Size) + self.recorderHandler = Recorder(channels=1) + self.recfile = None + + # path where audio files will be saved + if os.path.isdir(ROOT_PATH + "/Audio"): + print("Audio Directory is Available") + else: + print("Audio Directory is Unavailable, so that's why creating one") + os.makedirs(ROOT_PATH + "/Audio") + + self.path = ROOT_PATH + "/Audio/" + self.button.when_pressed = self.pressed + + def timeStamp(self): + """ + Generate time stamp + """ + now = datetime.now() + timestamp1 = int(datetime.timestamp(now)) + return str(timestamp1) + + def pressed(self): + print("Button is pressed") + recordingFileName = self.timeStamp() + recordingFileNameWithLocation = self.path + recordingFileName + ".wav" + print("Starting Recording") + self.startRecording(recordingFileNameWithLocation) + + def startRecording(self, name): + """ + Summary: records audio clip and saves it to appropiate location + + Parameters + ---------- + tag : recordingFileName + + TYPE: str + Description : + """ + print("In recordTag") + self.button.when_released = self.released + print("Saving with timestamp audio recording to loaction : {}".format(name)) + self.recfile = self.recorderHandler.open(name, 'wb') + self.recfile.start_recording() + print("Recording Started") + + def released(self): + """ + Summary: On button released save recorded Clip + """ + print("Button is depressed,Turning off recording") + self.recfile.stop_recording() + self.recfile.close() + print("Recording Finished") + self.button.when_released = None # Make button release to none diff --git a/rpyaudio_recorder/recorder.py b/rpyaudio_recorder/recorder.py index f1110caf5..a55848920 100644 --- a/rpyaudio_recorder/recorder.py +++ b/rpyaudio_recorder/recorder.py @@ -1,96 +1,96 @@ -# -*- coding: utf-8 -*- -'''recorder.py -Provides WAV recording functionality via two approaches: -Blocking mode (record for a set duration): ->>> rec = Recorder(channels=2) ->>> with rec.open('blocking.wav', 'wb') as recfile: -... recfile.record(duration=5.0) -Non-blocking mode (start and stop recording): ->>> rec = Recorder(channels=2) ->>> with rec.open('nonblocking.wav', 'wb') as recfile2: -... recfile2.start_recording() -... time.sleep(5.0) -... recfile2.stop_recording() -''' - -import pyaudio -import wave - - -class Recorder(object): - '''A recorder class for recording audio to a WAV file. - Records in mono by default. - ''' - - def __init__(self, channels=1, rate=16000, frames_per_buffer=1024 * 4): - self.channels = channels - self.rate = rate - self.frames_per_buffer = frames_per_buffer - - def open(self, fname, mode='wb'): - return RecordingFile(fname, mode, self.channels, self.rate, - self.frames_per_buffer) - - -class RecordingFile(object): - def __init__(self, fname, mode, channels, - rate, frames_per_buffer): - self.fname = fname - self.mode = mode - self.channels = channels - self.rate = rate - self.frames_per_buffer = frames_per_buffer - self._pa = pyaudio.PyAudio() - self.wavefile = self._prepare_file(self.fname, self.mode) - self._stream = None - - def __enter__(self): - return self - - def __exit__(self, exception, value, traceback): - self.close() - - def record(self, duration): - # Use a stream with no callback function in blocking mode - self._stream = self._pa.open(format=pyaudio.paInt16, - channels=self.channels, - rate=self.rate, - input=True, - frames_per_buffer=self.frames_per_buffer) - for _ in range(int(self.rate / self.frames_per_buffer * duration)): - audio = self._stream.read(self.frames_per_buffer) - self.wavefile.writeframes(audio) - return None - - def start_recording(self): - # Use a stream with a callback in non-blocking mode - self._stream = self._pa.open(format=pyaudio.paInt16, - channels=self.channels, - rate=self.rate, - input=True, - frames_per_buffer=self.frames_per_buffer, - stream_callback=self.get_callback()) - self._stream.start_stream() - return self - - def stop_recording(self): - self._stream.stop_stream() - return self - - def get_callback(self): - def callback(in_data, frame_count, time_info, status): - self.wavefile.writeframes(in_data) - return in_data, pyaudio.paContinue - return callback - - def close(self): - self._stream.close() - self._pa.terminate() - self.wavefile.close() - - def _prepare_file(self, fname, mode='wb'): - wavefile = wave.open(fname, mode) - wavefile.setnchannels(self.channels) - wavefile.setsampwidth(self._pa.get_sample_size(pyaudio.paInt16)) - wavefile.setframerate(self.rate) - return wavefile +# -*- coding: utf-8 -*- +'''recorder.py +Provides WAV recording functionality via two approaches: +Blocking mode (record for a set duration): +>>> rec = Recorder(channels=2) +>>> with rec.open('blocking.wav', 'wb') as recfile: +... recfile.record(duration=5.0) +Non-blocking mode (start and stop recording): +>>> rec = Recorder(channels=2) +>>> with rec.open('nonblocking.wav', 'wb') as recfile2: +... recfile2.start_recording() +... time.sleep(5.0) +... recfile2.stop_recording() +''' + +import pyaudio +import wave + + +class Recorder(object): + '''A recorder class for recording audio to a WAV file. + Records in mono by default. + ''' + + def __init__(self, channels=1, rate=16000, frames_per_buffer=1024 * 4): + self.channels = channels + self.rate = rate + self.frames_per_buffer = frames_per_buffer + + def open(self, fname, mode='wb'): + return RecordingFile(fname, mode, self.channels, self.rate, + self.frames_per_buffer) + + +class RecordingFile(object): + def __init__(self, fname, mode, channels, + rate, frames_per_buffer): + self.fname = fname + self.mode = mode + self.channels = channels + self.rate = rate + self.frames_per_buffer = frames_per_buffer + self._pa = pyaudio.PyAudio() + self.wavefile = self._prepare_file(self.fname, self.mode) + self._stream = None + + def __enter__(self): + return self + + def __exit__(self, exception, value, traceback): + self.close() + + def record(self, duration): + # Use a stream with no callback function in blocking mode + self._stream = self._pa.open(format=pyaudio.paInt16, + channels=self.channels, + rate=self.rate, + input=True, + frames_per_buffer=self.frames_per_buffer) + for _ in range(int(self.rate / self.frames_per_buffer * duration)): + audio = self._stream.read(self.frames_per_buffer) + self.wavefile.writeframes(audio) + return None + + def start_recording(self): + # Use a stream with a callback in non-blocking mode + self._stream = self._pa.open(format=pyaudio.paInt16, + channels=self.channels, + rate=self.rate, + input=True, + frames_per_buffer=self.frames_per_buffer, + stream_callback=self.get_callback()) + self._stream.start_stream() + return self + + def stop_recording(self): + self._stream.stop_stream() + return self + + def get_callback(self): + def callback(in_data, frame_count, time_info, status): + self.wavefile.writeframes(in_data) + return in_data, pyaudio.paContinue + return callback + + def close(self): + self._stream.close() + self._pa.terminate() + self.wavefile.close() + + def _prepare_file(self, fname, mode='wb'): + wavefile = wave.open(fname, mode) + wavefile.setnchannels(self.channels) + wavefile.setsampwidth(self._pa.get_sample_size(pyaudio.paInt16)) + wavefile.setframerate(self.rate) + return wavefile diff --git a/rpyaudio_recorder/requirements.txt b/rpyaudio_recorder/requirements.txt index 1c2b0488d..318d09e49 100644 --- a/rpyaudio_recorder/requirements.txt +++ b/rpyaudio_recorder/requirements.txt @@ -1,2 +1,2 @@ -PyAudio==0.2.11 +PyAudio==0.2.11 gpiozero==1.5.1 \ No newline at end of file diff --git a/scan_ports/README.md b/scan_ports/README.md index 00cedcae3..dc9b98d19 100644 --- a/scan_ports/README.md +++ b/scan_ports/README.md @@ -1,22 +1,22 @@ -# SCAN PORTS -This Port Scanner will work for both the Web Applications as well as remote Host. This tool has been created to provide the basic functionality of a Port Scanner. The general concept of Sockets had been used to provide the functionality. Port Scanner is built on Python 3 and uses some extra libraries such as socket and pyfigle - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -**Prerequisite** -- python3 - -**Modules used** -- sys -- socket -- datetime -- pyfiglet - -## How to use - +# SCAN PORTS +This Port Scanner will work for both the Web Applications as well as remote Host. This tool has been created to provide the basic functionality of a Port Scanner. The general concept of Sockets had been used to provide the functionality. Port Scanner is built on Python 3 and uses some extra libraries such as socket and pyfigle + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +**Prerequisite** +- python3 + +**Modules used** +- sys +- socket +- datetime +- pyfiglet + +## How to use + > python3 scan_port.py *localhost* \ No newline at end of file diff --git a/scan_ports/makefile b/scan_ports/makefile index 685dba5c9..b85d93685 100644 --- a/scan_ports/makefile +++ b/scan_ports/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ - fi +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ + fi diff --git a/scan_ports/requirements.txt b/scan_ports/requirements.txt index f480371b4..ed9488363 100644 --- a/scan_ports/requirements.txt +++ b/scan_ports/requirements.txt @@ -1 +1 @@ -pyfiglet (0.8.post1) +pyfiglet (0.8.post1) diff --git a/scan_ports/scan_port.py b/scan_ports/scan_port.py index 6208c9ae9..2731ff58d 100755 --- a/scan_ports/scan_port.py +++ b/scan_ports/scan_port.py @@ -1,42 +1,42 @@ -import pyfiglet -import sys -import socket -from datetime import datetime - -ascii_banner = pyfiglet.figlet_format("PORT SCANNER") -print(ascii_banner) - -# Defining a target -if len(sys.argv) == 2: - # translate hostname to IPv4 - target = socket.gethostbyname(sys.argv[1]) -else: - print("Invalid amount of Argument") - -# Add Banner -print("-" * 50) -print("Scanning Target: " + target) -print("Scanning started at:" + str(datetime.now())) -print("-" * 50) - -try: - # will scan ports between 1 to 65,535 - for port in range(1, 65535): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - socket.setdefaulttimeout(1) - - # returns an error indicator - result = s.connect_ex((target, port)) - if result == 0: - print("Port {} is open".format(port)) - s.close() - -except KeyboardInterrupt: - print("\nExitting Program !!!!") - sys.exit() -except socket.gaierror: - print("\nHostname Could Not Be Resolved !!!!") - sys.exit() -except socket.error: - print("\nServer not responding !!!!") - sys.exit() +import pyfiglet +import sys +import socket +from datetime import datetime + +ascii_banner = pyfiglet.figlet_format("PORT SCANNER") +print(ascii_banner) + +# Defining a target +if len(sys.argv) == 2: + # translate hostname to IPv4 + target = socket.gethostbyname(sys.argv[1]) +else: + print("Invalid amount of Argument") + +# Add Banner +print("-" * 50) +print("Scanning Target: " + target) +print("Scanning started at:" + str(datetime.now())) +print("-" * 50) + +try: + # will scan ports between 1 to 65,535 + for port in range(1, 65535): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + socket.setdefaulttimeout(1) + + # returns an error indicator + result = s.connect_ex((target, port)) + if result == 0: + print("Port {} is open".format(port)) + s.close() + +except KeyboardInterrupt: + print("\nExitting Program !!!!") + sys.exit() +except socket.gaierror: + print("\nHostname Could Not Be Resolved !!!!") + sys.exit() +except socket.error: + print("\nServer not responding !!!!") + sys.exit() diff --git a/screen_recorder/README.md b/screen_recorder/README.md index 4518f690c..25ba5e955 100644 --- a/screen_recorder/README.md +++ b/screen_recorder/README.md @@ -1,26 +1,26 @@ -# Screen Recorder - -Record your screen and save it as a 1080p 60fps .avi file. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -### Pre-requisites -Setup virtual environment from previous step or install requirements manually: -``` -$ pip install numpy -$ pip install opencv-python -$ pip install pyautogui -``` - -### How to Use -``` -$ python screen_recorder.py -``` -- Press `s` : Start the screen recording -- Press `w` : Pause/Resume the screen recording -- Press `q` : End the screen recording +# Screen Recorder + +Record your screen and save it as a 1080p 60fps .avi file. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +### Pre-requisites +Setup virtual environment from previous step or install requirements manually: +``` +$ pip install numpy +$ pip install opencv-python +$ pip install pyautogui +``` + +### How to Use +``` +$ python screen_recorder.py +``` +- Press `s` : Start the screen recording +- Press `w` : Pause/Resume the screen recording +- Press `q` : End the screen recording diff --git a/screen_recorder/makefile b/screen_recorder/makefile index e78e53c81..7aafa604a 100644 --- a/screen_recorder/makefile +++ b/screen_recorder/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/screen_recorder/reqirements.txt b/screen_recorder/reqirements.txt index c21b90e06..c5ca87e62 100644 --- a/screen_recorder/reqirements.txt +++ b/screen_recorder/reqirements.txt @@ -1,3 +1,3 @@ -numpy==1.19.2 -opencv-python==4.4.0.44 +numpy==1.19.2 +opencv-python==4.4.0.44 PyAutoGUI==0.9.52 \ No newline at end of file diff --git a/screen_recorder/screen_recorder.py b/screen_recorder/screen_recorder.py index 5fe2b8145..204762374 100644 --- a/screen_recorder/screen_recorder.py +++ b/screen_recorder/screen_recorder.py @@ -1,52 +1,52 @@ -import numpy as np -import pyautogui -import cv2 -import datetime as dt - -print("Key Commands:") -print("s - Start") -print("w - Pause/Resume") -print("q - Quit") - -# Create VideoWriter -resolution = (1920, 1080) -fps = 60 -codec = cv2.VideoWriter_fourcc(*'XVID') -filename = dt.datetime.now().strftime('%m-%d-%Y_%H-%M_recording.avi') - -recording = cv2.VideoWriter(filename, codec, fps, resolution) - -# Create preview window -cv2.namedWindow('Preview', cv2.WINDOW_NORMAL) -cv2.resizeWindow('Preview', 480, 270) - -start = False -pause = False - -while True: - # Record when the process has started but if it's not paused - if start and not pause: - screen = pyautogui.screenshot() - frame = np.array(screen) - frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) - - recording.write(frame) - cv2.imshow('Preview', frame) - - key = cv2.waitKey(1) # Receive key commands - if key == ord('q'): - print("Recording ended.") - break - elif key == ord('s'): - if not start: - print("Recording started. Press 'q' to end recording.") - start = True - elif key == ord('w') and start: - pause = not pause - if pause: - print("Recording paused. Press 'w' to resume recording.") - else: - print("Recording resumed.") - -recording.release() -cv2.destroyAllWindows() +import numpy as np +import pyautogui +import cv2 +import datetime as dt + +print("Key Commands:") +print("s - Start") +print("w - Pause/Resume") +print("q - Quit") + +# Create VideoWriter +resolution = (1920, 1080) +fps = 60 +codec = cv2.VideoWriter_fourcc(*'XVID') +filename = dt.datetime.now().strftime('%m-%d-%Y_%H-%M_recording.avi') + +recording = cv2.VideoWriter(filename, codec, fps, resolution) + +# Create preview window +cv2.namedWindow('Preview', cv2.WINDOW_NORMAL) +cv2.resizeWindow('Preview', 480, 270) + +start = False +pause = False + +while True: + # Record when the process has started but if it's not paused + if start and not pause: + screen = pyautogui.screenshot() + frame = np.array(screen) + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + + recording.write(frame) + cv2.imshow('Preview', frame) + + key = cv2.waitKey(1) # Receive key commands + if key == ord('q'): + print("Recording ended.") + break + elif key == ord('s'): + if not start: + print("Recording started. Press 'q' to end recording.") + start = True + elif key == ord('w') and start: + pause = not pause + if pause: + print("Recording paused. Press 'w' to resume recording.") + else: + print("Recording resumed.") + +recording.release() +cv2.destroyAllWindows() diff --git a/screen_shoter/README.md b/screen_shoter/README.md index bfdd6a59b..abad66cdf 100644 --- a/screen_shoter/README.md +++ b/screen_shoter/README.md @@ -1,15 +1,15 @@ -# Screenshoter - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -Take screenshots with two clicks on screen (top-left and bottom-right). - -* Press Up key : For defining particular window to take screenshots on. -* Press Click : To set top-left coordinates. -* Press Click : To set bottom-right coordinates. -* Press Down Key : For capturing and storing image. +# Screenshoter + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +Take screenshots with two clicks on screen (top-left and bottom-right). + +* Press Up key : For defining particular window to take screenshots on. +* Press Click : To set top-left coordinates. +* Press Click : To set bottom-right coordinates. +* Press Down Key : For capturing and storing image. diff --git a/screen_shoter/makefile b/screen_shoter/makefile index e78e53c81..7aafa604a 100644 --- a/screen_shoter/makefile +++ b/screen_shoter/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/screen_shoter/reqirements.txt b/screen_shoter/reqirements.txt index d6404804a..fdf0958af 100644 --- a/screen_shoter/reqirements.txt +++ b/screen_shoter/reqirements.txt @@ -1,4 +1,4 @@ -pynput==1.7.1 -numpy==1.18.1 -PyAutoGUI==0.9.52 +pynput==1.7.1 +numpy==1.18.1 +PyAutoGUI==0.9.52 opencv-python==4.4.0.44 \ No newline at end of file diff --git a/screen_shoter/screenshooter.py b/screen_shoter/screenshooter.py index e415abad5..54a33dc2d 100644 --- a/screen_shoter/screenshooter.py +++ b/screen_shoter/screenshooter.py @@ -1,101 +1,101 @@ -import cv2 -import numpy as np -import pynput.mouse as ms -import pynput.keyboard as kb -from pynput.keyboard import Key, Controller -import pyautogui - -keyboard = Controller() - - -class TwoClicksScreenShot: - clickCount = 0 - pCords = [0, 0, 0, 0] - defined = False - screenShot = None - filename = "screenshot" - - @staticmethod - def area_select(): - - print('Click twice to define Screenshot area') - - def on_click(x, y, button, pressed): - - if pressed: - - if TwoClicksScreenShot.clickCount == 0: - print('First point ({0}, {1})'.format(x, y)) - TwoClicksScreenShot.pCords[0] = x - TwoClicksScreenShot.pCords[1] = y - elif TwoClicksScreenShot.clickCount == 1: - print('Second point ({0}, {1})'.format(x, y)) - TwoClicksScreenShot.pCords[2] = x - TwoClicksScreenShot.pCords[0] - TwoClicksScreenShot.pCords[3] = y - TwoClicksScreenShot.pCords[1] - TwoClicksScreenShot.defined = True - print('') - TwoClicksScreenShot.clickCount = 0 - return False - TwoClicksScreenShot.clickCount += 1 - - with ms.Listener(on_click=on_click) as listener: - listener.join() - - @staticmethod - def keypress(): - - print('Press UP key to define Screenshot Area') - - def on_release(key): - if key == Key.up: - print('Pressed\n') - TwoClicksScreenShot.area_select() - if TwoClicksScreenShot.capture(): - return False - else: - print('Define points properly!! Press UP again to define') - return True - - with kb.Listener(on_release=on_release) as listener: - listener.join() - - @staticmethod - def start_typing(): - - print('Press DOWN key to capture') - - def on_release(key): - if key == Key.down: - print('Pressed\n') - TwoClicksScreenShot.output() - return False - - with kb.Listener(on_release=on_release) as listener: - listener.join() - - @staticmethod - def capture(): - if TwoClicksScreenShot.pCords[2] <= 0 or TwoClicksScreenShot.pCords[3] <= 0: - return False - - if TwoClicksScreenShot.defined: - TwoClicksScreenShot.screenShot = pyautogui.screenshot(region=(TwoClicksScreenShot.pCords[0], - TwoClicksScreenShot.pCords[1], - TwoClicksScreenShot.pCords[2], - TwoClicksScreenShot.pCords[3])) - TwoClicksScreenShot.screenShot = cv2.cvtColor(np.array(TwoClicksScreenShot.screenShot), cv2.COLOR_BGR2RGB) - return True - - @staticmethod - def output(): - cv2.imwrite(TwoClicksScreenShot.filename + ".png", TwoClicksScreenShot.screenShot) - print("Screenshot saved as " + TwoClicksScreenShot.filename + ".png") - - -def start(): - TwoClicksScreenShot.keypress() - TwoClicksScreenShot.start_typing() - - -if __name__ == '__main__': - start() +import cv2 +import numpy as np +import pynput.mouse as ms +import pynput.keyboard as kb +from pynput.keyboard import Key, Controller +import pyautogui + +keyboard = Controller() + + +class TwoClicksScreenShot: + clickCount = 0 + pCords = [0, 0, 0, 0] + defined = False + screenShot = None + filename = "screenshot" + + @staticmethod + def area_select(): + + print('Click twice to define Screenshot area') + + def on_click(x, y, button, pressed): + + if pressed: + + if TwoClicksScreenShot.clickCount == 0: + print('First point ({0}, {1})'.format(x, y)) + TwoClicksScreenShot.pCords[0] = x + TwoClicksScreenShot.pCords[1] = y + elif TwoClicksScreenShot.clickCount == 1: + print('Second point ({0}, {1})'.format(x, y)) + TwoClicksScreenShot.pCords[2] = x - TwoClicksScreenShot.pCords[0] + TwoClicksScreenShot.pCords[3] = y - TwoClicksScreenShot.pCords[1] + TwoClicksScreenShot.defined = True + print('') + TwoClicksScreenShot.clickCount = 0 + return False + TwoClicksScreenShot.clickCount += 1 + + with ms.Listener(on_click=on_click) as listener: + listener.join() + + @staticmethod + def keypress(): + + print('Press UP key to define Screenshot Area') + + def on_release(key): + if key == Key.up: + print('Pressed\n') + TwoClicksScreenShot.area_select() + if TwoClicksScreenShot.capture(): + return False + else: + print('Define points properly!! Press UP again to define') + return True + + with kb.Listener(on_release=on_release) as listener: + listener.join() + + @staticmethod + def start_typing(): + + print('Press DOWN key to capture') + + def on_release(key): + if key == Key.down: + print('Pressed\n') + TwoClicksScreenShot.output() + return False + + with kb.Listener(on_release=on_release) as listener: + listener.join() + + @staticmethod + def capture(): + if TwoClicksScreenShot.pCords[2] <= 0 or TwoClicksScreenShot.pCords[3] <= 0: + return False + + if TwoClicksScreenShot.defined: + TwoClicksScreenShot.screenShot = pyautogui.screenshot(region=(TwoClicksScreenShot.pCords[0], + TwoClicksScreenShot.pCords[1], + TwoClicksScreenShot.pCords[2], + TwoClicksScreenShot.pCords[3])) + TwoClicksScreenShot.screenShot = cv2.cvtColor(np.array(TwoClicksScreenShot.screenShot), cv2.COLOR_BGR2RGB) + return True + + @staticmethod + def output(): + cv2.imwrite(TwoClicksScreenShot.filename + ".png", TwoClicksScreenShot.screenShot) + print("Screenshot saved as " + TwoClicksScreenShot.filename + ".png") + + +def start(): + TwoClicksScreenShot.keypress() + TwoClicksScreenShot.start_typing() + + +if __name__ == '__main__': + start() diff --git a/send_sms/README.md b/send_sms/README.md index bd251a622..3ba68d217 100644 --- a/send_sms/README.md +++ b/send_sms/README.md @@ -1,20 +1,20 @@ -# Send SMS with Twilio -Simple sms sender using Twilio python module. - -# Python requirements -Python 3.6 or newer - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## Installation - -Setup virtual environment from previous step or install requirements manually: - -```bash -pip install -r requirements.txt +# Send SMS with Twilio +Simple sms sender using Twilio python module. + +# Python requirements +Python 3.6 or newer + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## Installation + +Setup virtual environment from previous step or install requirements manually: + +```bash +pip install -r requirements.txt ``` \ No newline at end of file diff --git a/send_sms/makefile b/send_sms/makefile index e78e53c81..7aafa604a 100644 --- a/send_sms/makefile +++ b/send_sms/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/send_sms/sms.py b/send_sms/sms.py index 5dcbbacb5..5b26543c6 100644 --- a/send_sms/sms.py +++ b/send_sms/sms.py @@ -1,36 +1,36 @@ -from twilio.rest import Client - -sid = 'ACCOUNT SID goes here' -auth_token = 'AUTH token here' - -twilio_number = 'Your Twilio provided number here' - -client = Client(sid, auth_token) - -details = {'Message created': '', 'Date sent': '', 'Body': ''} - - -def craft(msg, fromPhone, sendTo): - message = client.messages.create( - body=msg, - from_=fromPhone, - to=sendTo - ) - - details['Message created'] = str(message.date_created) - details['Date sent'] = str(message.date_sent) - details['Body'] = str(message.body) - - -def main(msg: str): - return craft(msg, twilio_number, '+15555550100') - - -if __name__ == '__main__': - main('Hello, user! Sent from Python!') - seeDetails = input('See details of this message? [y/n]: ') - if seeDetails.lower() == 'y': - for i in details: - print(f'{i} = {details[i]}') - else: - exit() +from twilio.rest import Client + +sid = 'ACCOUNT SID goes here' +auth_token = 'AUTH token here' + +twilio_number = 'Your Twilio provided number here' + +client = Client(sid, auth_token) + +details = {'Message created': '', 'Date sent': '', 'Body': ''} + + +def craft(msg, fromPhone, sendTo): + message = client.messages.create( + body=msg, + from_=fromPhone, + to=sendTo + ) + + details['Message created'] = str(message.date_created) + details['Date sent'] = str(message.date_sent) + details['Body'] = str(message.body) + + +def main(msg: str): + return craft(msg, twilio_number, '+15555550100') + + +if __name__ == '__main__': + main('Hello, user! Sent from Python!') + seeDetails = input('See details of this message? [y/n]: ') + if seeDetails.lower() == 'y': + for i in details: + print(f'{i} = {details[i]}') + else: + exit() diff --git a/simple_plagiarism_detector/README.md b/simple_plagiarism_detector/README.md index 18e54ce77..2cb84c58e 100644 --- a/simple_plagiarism_detector/README.md +++ b/simple_plagiarism_detector/README.md @@ -1,27 +1,27 @@ -# Simple Plagiarism Checker - -This is the simplest way to calculate similarity between two texts. Using cosine similarity between them. So, it is rather a similarity measure between two texts. Which in this case might be useful when comparing two texts for similarity/plagiarism. - -## Requirements -Only uses in-built Python packages. - -## Usage - -Specify the text files you want to compare while running the script as arguments. - -`$ python simple-plagiarism-detector.py file1.txt file2.txt` - -**Sample Output:** - -`file1.txt` contents -> This is an example sentence - -`file2.txt` contents -> This sentence is similar to an example sentence - - -`$ python simple-plagiarism-detector.py file1.txt file2.txt` - -Similarity Score: 0.8485281374238569 - +# Simple Plagiarism Checker + +This is the simplest way to calculate similarity between two texts. Using cosine similarity between them. So, it is rather a similarity measure between two texts. Which in this case might be useful when comparing two texts for similarity/plagiarism. + +## Requirements +Only uses in-built Python packages. + +## Usage + +Specify the text files you want to compare while running the script as arguments. + +`$ python simple-plagiarism-detector.py file1.txt file2.txt` + +**Sample Output:** + +`file1.txt` contents +> This is an example sentence + +`file2.txt` contents +> This sentence is similar to an example sentence + + +`$ python simple-plagiarism-detector.py file1.txt file2.txt` + +Similarity Score: 0.8485281374238569 + **Contributor:** [abhinand5](https://github.com/abhinand5) \ No newline at end of file diff --git a/simple_plagiarism_detector/simple-plagiarism-detector.py b/simple_plagiarism_detector/simple-plagiarism-detector.py index 66592af63..ae14a20b5 100644 --- a/simple_plagiarism_detector/simple-plagiarism-detector.py +++ b/simple_plagiarism_detector/simple-plagiarism-detector.py @@ -1,54 +1,54 @@ -# Simple plagiarism detector -# Note: This is a very simple example, might not work perfectly -# Author: Abhinand - -import math -import re -from collections import Counter -import sys - -WORD = re.compile(r"[A-Za-z0-9]") -SPECIAL_CHARS = re.compile(r"[^A-Za-z0-9]") - - -def get_cosine(vec1, vec2): - """ Function to compute Cosine Similarity between two word vectors""" - intersection = set(vec1.keys()) & set(vec2.keys()) - numerator = sum([vec1[x] * vec2[x] for x in intersection]) - - sum1 = sum([vec1[x] ** 2 for x in list(vec1.keys())]) - sum2 = sum([vec2[x] ** 2 for x in list(vec2.keys())]) - denominator = math.sqrt(sum1) * math.sqrt(sum2) - - if not denominator: - return 0.0 - else: - return float(numerator) / denominator - - -def text_to_vector(text): - """Simple function to convert text to vector""" - words = WORD.findall(text) - special = SPECIAL_CHARS.findall(text) - return Counter(words) + Counter(special) - - -if __name__ == "__main__": - - file1 = open(sys.argv[1], "r") - text1 = file1.read().replace("\n", " ") - - file2 = open(sys.argv[2], "r") - text2 = file2.read().replace("\n", " ") - - if len(text1) == 0 and len(text2) == 0: - print("given text files were empty, imputing '1' as place holder") - text1 = '' + '1' - text2 = '' + '1' - - vector1 = text_to_vector(text1) - vector2 = text_to_vector(text2) - - cosine = round(get_cosine(vector1, vector2), 2) - - print("Similarity Score:", cosine) +# Simple plagiarism detector +# Note: This is a very simple example, might not work perfectly +# Author: Abhinand + +import math +import re +from collections import Counter +import sys + +WORD = re.compile(r"[A-Za-z0-9]") +SPECIAL_CHARS = re.compile(r"[^A-Za-z0-9]") + + +def get_cosine(vec1, vec2): + """ Function to compute Cosine Similarity between two word vectors""" + intersection = set(vec1.keys()) & set(vec2.keys()) + numerator = sum([vec1[x] * vec2[x] for x in intersection]) + + sum1 = sum([vec1[x] ** 2 for x in list(vec1.keys())]) + sum2 = sum([vec2[x] ** 2 for x in list(vec2.keys())]) + denominator = math.sqrt(sum1) * math.sqrt(sum2) + + if not denominator: + return 0.0 + else: + return float(numerator) / denominator + + +def text_to_vector(text): + """Simple function to convert text to vector""" + words = WORD.findall(text) + special = SPECIAL_CHARS.findall(text) + return Counter(words) + Counter(special) + + +if __name__ == "__main__": + + file1 = open(sys.argv[1], "r") + text1 = file1.read().replace("\n", " ") + + file2 = open(sys.argv[2], "r") + text2 = file2.read().replace("\n", " ") + + if len(text1) == 0 and len(text2) == 0: + print("given text files were empty, imputing '1' as place holder") + text1 = '' + '1' + text2 = '' + '1' + + vector1 = text_to_vector(text1) + vector2 = text_to_vector(text2) + + cosine = round(get_cosine(vector1, vector2), 2) + + print("Similarity Score:", cosine) diff --git a/sms_location/README.md b/sms_location/README.md index 9a48b96c6..61a2a5fe3 100644 --- a/sms_location/README.md +++ b/sms_location/README.md @@ -1,21 +1,21 @@ - -# Sms_Location - -# How to get Dev-Api -- Register your phone no on [Fast2Sms](https://www.fast2sms.com) -- Enter your valid Api-Key in authorization - - ```python - query={"authorization":"your api key ", #copy paste your api-key - "sender_id":"FSTSMS", - "message":msg, - "language":"english", - "route":"p", - "numbers":no - } - ``` -- Run your script and enter the valid mobile no at which you wanted to send your location - -# Screen-shots - + +# Sms_Location + +# How to get Dev-Api +- Register your phone no on [Fast2Sms](https://www.fast2sms.com) +- Enter your valid Api-Key in authorization + + ```python + query={"authorization":"your api key ", #copy paste your api-key + "sender_id":"FSTSMS", + "message":msg, + "language":"english", + "route":"p", + "numbers":no + } + ``` +- Run your script and enter the valid mobile no at which you wanted to send your location + +# Screen-shots + ![Screenshot_2020-10-13-14-04-27-100_com android mms](https://user-images.githubusercontent.com/42912055/95842393-1ed37f80-0d64-11eb-86bb-998144966ff5.jpg) \ No newline at end of file diff --git a/sms_location/requirements.txt b/sms_location/requirements.txt index c65ee24a9..66e1737c7 100644 --- a/sms_location/requirements.txt +++ b/sms_location/requirements.txt @@ -1,6 +1,6 @@ -certifi==2020.6.20 -chardet==3.0.4 -idna==2.10 -jason==0.1.7 -requests==2.24.0 +certifi==2020.6.20 +chardet==3.0.4 +idna==2.10 +jason==0.1.7 +requests==2.24.0 urllib3==1.25.10 \ No newline at end of file diff --git a/sms_location/sms_loc.py b/sms_location/sms_loc.py index 156afb459..a8051f628 100644 --- a/sms_location/sms_loc.py +++ b/sms_location/sms_loc.py @@ -1,23 +1,23 @@ -import requests -no = input("enter your no") -r = requests.get('https://get.geojs.io/') -ip_request = requests.get('https://get.geojs.io/v1/ip.json') -ipadd = ip_request.json()['ip'] -url = 'https://get.geojs.io/v1/ip/geo/' + ipadd + '.json' -geo_request = requests.get(url) -geo_data = geo_request.json() -msg = f"latitude: {geo_data['latitude']} longitude : {geo_data['longitude']} city : {geo_data['city']}" -url1 = "https://www.fast2sms.com/dev/bulk" -query = {"authorization" : "your api key ", - "sender_id" : "FSTSMS", - "message" : msg, - "language" : "english", - "route" : "p", - "numbers" : no - } - -headers = { - 'cache-control' : "no-cache" -} -response = requests.request("GET", url1, headers=headers, params=query) -print(response.text) +import requests +no = input("enter your no") +r = requests.get('https://get.geojs.io/') +ip_request = requests.get('https://get.geojs.io/v1/ip.json') +ipadd = ip_request.json()['ip'] +url = 'https://get.geojs.io/v1/ip/geo/' + ipadd + '.json' +geo_request = requests.get(url) +geo_data = geo_request.json() +msg = f"latitude: {geo_data['latitude']} longitude : {geo_data['longitude']} city : {geo_data['city']}" +url1 = "https://www.fast2sms.com/dev/bulk" +query = {"authorization" : "your api key ", + "sender_id" : "FSTSMS", + "message" : msg, + "language" : "english", + "route" : "p", + "numbers" : no + } + +headers = { + 'cache-control' : "no-cache" +} +response = requests.request("GET", url1, headers=headers, params=query) +print(response.text) diff --git a/speed_tester/README.md b/speed_tester/README.md index 39436e1c7..b5b062651 100644 --- a/speed_tester/README.md +++ b/speed_tester/README.md @@ -1,12 +1,12 @@ -# Speed tester for internet connections -A short script useful for checking internet connection speeds coded in python. -## Installation -Script was developed using python 3.8 so it needs to be installed for the script to run.\ -Simply `pip3 install -r requirements.txt` to add required packages. -## Usage -Type `python3 speed_tester.py` and after a short while you'll see output in a form: -``` -Average ping time for google.com is: xxxms -Download speed is: xxxbps -Upload speed is: xxxbps +# Speed tester for internet connections +A short script useful for checking internet connection speeds coded in python. +## Installation +Script was developed using python 3.8 so it needs to be installed for the script to run.\ +Simply `pip3 install -r requirements.txt` to add required packages. +## Usage +Type `python3 speed_tester.py` and after a short while you'll see output in a form: +``` +Average ping time for google.com is: xxxms +Download speed is: xxxbps +Upload speed is: xxxbps ``` \ No newline at end of file diff --git a/speed_tester/speed_tester.py b/speed_tester/speed_tester.py index 397b99583..a5c1b805e 100644 --- a/speed_tester/speed_tester.py +++ b/speed_tester/speed_tester.py @@ -1,51 +1,51 @@ -import speedtest -import subprocess -import platform -import re - - -def ping_google(): - try: - system = platform.system().lower() - option = "n" if system == "windows" else "c" - res = subprocess.check_output( - f"ping -{option} 10 google.com", - shell=True, universal_newlines=True - ) - if "unreachable" in res: - return False - else: - return res - except Exception: - return False - - -def test_speed(): - units = ["bps", "Kbps", "Mbps", "Gbps"] - test = speedtest.Speedtest() - download_speed = test.download() - unit_index = 0 - while download_speed > 999: - download_speed /= 1000 - unit_index += 1 - download_units = units[unit_index] - upload_speed = test.upload() - unit_index = 0 - while upload_speed > 999: - upload_speed /= 1000 - unit_index += 1 - upload_units = units[unit_index] - ping = ping_google() - if ping: - times = re.findall(r"(?<=time=)\d+\.?\d*", ping) - times = [float(time) for time in times] - av_ping = sum(times) / len(times) - print(f"Average ping time for google.com is: {av_ping}ms") - else: - print("Can't connect to google.com") - print(f"Download speed is: {round(download_speed, 3)}{download_units}") - print(f"Upload speed is: {round(upload_speed, 3)}{upload_units}") - - -if __name__ == "__main__": - test_speed() +import speedtest +import subprocess +import platform +import re + + +def ping_google(): + try: + system = platform.system().lower() + option = "n" if system == "windows" else "c" + res = subprocess.check_output( + f"ping -{option} 10 google.com", + shell=True, universal_newlines=True + ) + if "unreachable" in res: + return False + else: + return res + except Exception: + return False + + +def test_speed(): + units = ["bps", "Kbps", "Mbps", "Gbps"] + test = speedtest.Speedtest() + download_speed = test.download() + unit_index = 0 + while download_speed > 999: + download_speed /= 1000 + unit_index += 1 + download_units = units[unit_index] + upload_speed = test.upload() + unit_index = 0 + while upload_speed > 999: + upload_speed /= 1000 + unit_index += 1 + upload_units = units[unit_index] + ping = ping_google() + if ping: + times = re.findall(r"(?<=time=)\d+\.?\d*", ping) + times = [float(time) for time in times] + av_ping = sum(times) / len(times) + print(f"Average ping time for google.com is: {av_ping}ms") + else: + print("Can't connect to google.com") + print(f"Download speed is: {round(download_speed, 3)}{download_units}") + print(f"Upload speed is: {round(upload_speed, 3)}{upload_units}") + + +if __name__ == "__main__": + test_speed() diff --git a/spell_corrector/README.md b/spell_corrector/README.md index 756b55952..e7fda71d6 100644 --- a/spell_corrector/README.md +++ b/spell_corrector/README.md @@ -1,2 +1,2 @@ -# Spelling Corrector +# Spelling Corrector Just select a text file from the tkinter dialogue box and the spellings will be corrected in the file. \ No newline at end of file diff --git a/spell_corrector/makefile b/spell_corrector/makefile index e78e53c81..7aafa604a 100644 --- a/spell_corrector/makefile +++ b/spell_corrector/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/spell_corrector/spell_corrector.py b/spell_corrector/spell_corrector.py index a27ae37a5..3a45e5cee 100644 --- a/spell_corrector/spell_corrector.py +++ b/spell_corrector/spell_corrector.py @@ -1,23 +1,23 @@ -from textblob import TextBlob -from tkinter import Tk -from tkinter import filedialog - -gui = Tk() -gui.filename = filedialog.askopenfilename(initialdir="/", - title="Select file", - filetypes=(("txt files", - ".txt"), - ("all files", ".*"))) -f = open(gui.filename, 'r') -s = [] -for i in f: - s.append(i) -f.close() -for i in range(len(s)): - s[i] = TextBlob(s[i]) - s[i] = s[i].correct() -f = open(gui.filename, 'w') -for i in range(len(s)): - s[i] = str(s[i]) - f.write(s[i]) -f.close() +from textblob import TextBlob +from tkinter import Tk +from tkinter import filedialog + +gui = Tk() +gui.filename = filedialog.askopenfilename(initialdir="/", + title="Select file", + filetypes=(("txt files", + ".txt"), + ("all files", ".*"))) +f = open(gui.filename, 'r') +s = [] +for i in f: + s.append(i) +f.close() +for i in range(len(s)): + s[i] = TextBlob(s[i]) + s[i] = s[i].correct() +f = open(gui.filename, 'w') +for i in range(len(s)): + s[i] = str(s[i]) + f.write(s[i]) +f.close() diff --git a/stop_watch/README.md b/stop_watch/README.md index 36500b5dc..5f6431b42 100644 --- a/stop_watch/README.md +++ b/stop_watch/README.md @@ -1,12 +1,12 @@ -# Stopwatch - with features Start, Stop and Reset - -## Required Python libraries for running the program - -- tkinter -- datetime - -### steps to run the stopwatch - -1. Open and run .py file. -2. A dialog box will appear with 3 options(start,stop,reset) in the bottom. -3. Click **Start** button to start the Stopwatch. -4. Click **Stop** button to stop and you can again click on **Start** to resume. -5. Click on **Reset** button to reset the time. +# Stopwatch - with features Start, Stop and Reset + +## Required Python libraries for running the program - +- tkinter +- datetime + +### steps to run the stopwatch - +1. Open and run .py file. +2. A dialog box will appear with 3 options(start,stop,reset) in the bottom. +3. Click **Start** button to start the Stopwatch. +4. Click **Stop** button to stop and you can again click on **Start** to resume. +5. Click on **Reset** button to reset the time. diff --git a/stop_watch/Stopwatch.py b/stop_watch/Stopwatch.py index 69f72fb4b..d306f917e 100644 --- a/stop_watch/Stopwatch.py +++ b/stop_watch/Stopwatch.py @@ -1,88 +1,88 @@ -# importing the required libraries -import tkinter as Tkinter -from datetime import datetime - -counter = 66600 -running = False - - -def counter_label(label): - def count(): - if running: - global counter - - # To manage the initial delay. - if counter == 66600: - display = "Starting" - else: - tt = datetime.fromtimestamp(counter) - string = tt.strftime("%H:%M:%S") - display = string - - label['text'] = display # Or label.config(text=display) - - # label.after(arg1, arg2) delays by - # first argument given in milliseconds - # and then calls the function given as second argument. - # Generally like here we need to call the - # function in which it is present repeatedly. - # Delays by 1000ms=1 seconds and call count again. - label.after(1000, count) - counter += 1 - - # Triggering the start of the counter. - count() - - -# start function of the stopwatch -def Start(label): - global running - running = True - counter_label(label) - start['state'] = 'disabled' - stop['state'] = 'normal' - reset['state'] = 'normal' - - -# Stop function of the stopwatch -def Stop(): - global running - start['state'] = 'normal' - stop['state'] = 'disabled' - reset['state'] = 'normal' - running = False - - -# Reset function of the stopwatch -def Reset(label): - global counter - counter = 66600 - - # If reset is pressed after pressing stop. - if running is False: - reset['state'] = 'disabled' - label['text'] = 'Welcome!' - - # If reset is pressed while the stopwatch is running. - else: - label['text'] = 'Starting' - - -root = Tkinter.Tk() -root.title("Stopwatch") - -# Fixing the window size. -root.minsize(width=250, height=70) -label = Tkinter.Label(root, text="Welcome!", fg="black", - font="Verdana 30 bold") -label.pack() -f = Tkinter.Frame(root) -start = Tkinter.Button(f, text='Start', width=6, command=lambda: Start(label)) -stop = Tkinter.Button(f, text='Stop', width=6, state='disabled', command=Stop) -reset = Tkinter.Button(f, text='Reset', width=6, state='disabled', - command=lambda: Reset(label)) -f.pack(anchor='center', pady=5) -start.pack(side="left") -stop.pack(side="left") -reset.pack(side="left") -root.mainloop() +# importing the required libraries +import tkinter as Tkinter +from datetime import datetime + +counter = 66600 +running = False + + +def counter_label(label): + def count(): + if running: + global counter + + # To manage the initial delay. + if counter == 66600: + display = "Starting" + else: + tt = datetime.fromtimestamp(counter) + string = tt.strftime("%H:%M:%S") + display = string + + label['text'] = display # Or label.config(text=display) + + # label.after(arg1, arg2) delays by + # first argument given in milliseconds + # and then calls the function given as second argument. + # Generally like here we need to call the + # function in which it is present repeatedly. + # Delays by 1000ms=1 seconds and call count again. + label.after(1000, count) + counter += 1 + + # Triggering the start of the counter. + count() + + +# start function of the stopwatch +def Start(label): + global running + running = True + counter_label(label) + start['state'] = 'disabled' + stop['state'] = 'normal' + reset['state'] = 'normal' + + +# Stop function of the stopwatch +def Stop(): + global running + start['state'] = 'normal' + stop['state'] = 'disabled' + reset['state'] = 'normal' + running = False + + +# Reset function of the stopwatch +def Reset(label): + global counter + counter = 66600 + + # If reset is pressed after pressing stop. + if running is False: + reset['state'] = 'disabled' + label['text'] = 'Welcome!' + + # If reset is pressed while the stopwatch is running. + else: + label['text'] = 'Starting' + + +root = Tkinter.Tk() +root.title("Stopwatch") + +# Fixing the window size. +root.minsize(width=250, height=70) +label = Tkinter.Label(root, text="Welcome!", fg="black", + font="Verdana 30 bold") +label.pack() +f = Tkinter.Frame(root) +start = Tkinter.Button(f, text='Start', width=6, command=lambda: Start(label)) +stop = Tkinter.Button(f, text='Stop', width=6, state='disabled', command=Stop) +reset = Tkinter.Button(f, text='Reset', width=6, state='disabled', + command=lambda: Reset(label)) +f.pack(anchor='center', pady=5) +start.pack(side="left") +stop.pack(side="left") +reset.pack(side="left") +root.mainloop() diff --git a/subtitle_creator/README.md b/subtitle_creator/README.md index 81231e3ee..30842b6e5 100644 --- a/subtitle_creator/README.md +++ b/subtitle_creator/README.md @@ -1,10 +1,10 @@ -# Subtitle creator - -Program takes 2 or 3 arguments, video filename you want subtitles to be read from, font size of subtitles ( optional , default is 15) and the output video file name. -``` -python subtitle_creator.py video.mp4 output.mp4 -``` -or -``` -python subtitle_creator.py video.mp4 20 output.mp4 -``` +# Subtitle creator + +Program takes 2 or 3 arguments, video filename you want subtitles to be read from, font size of subtitles ( optional , default is 15) and the output video file name. +``` +python subtitle_creator.py video.mp4 output.mp4 +``` +or +``` +python subtitle_creator.py video.mp4 20 output.mp4 +``` diff --git a/subtitle_creator/requirements.txt b/subtitle_creator/requirements.txt index f65ef4137..6e6c7d46b 100644 --- a/subtitle_creator/requirements.txt +++ b/subtitle_creator/requirements.txt @@ -1,4 +1,4 @@ -moviepy -speech_recognition -wave -contextlib +moviepy +speech_recognition +wave +contextlib diff --git a/subtitle_creator/subtitle_creator.py b/subtitle_creator/subtitle_creator.py index b73fe565a..0fce52bfa 100644 --- a/subtitle_creator/subtitle_creator.py +++ b/subtitle_creator/subtitle_creator.py @@ -1,54 +1,54 @@ -import moviepy.editor as mp -import speech_recognition as sr -import wave -import contextlib -from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip -import sys - - -def get_audio(filename): - video = mp.VideoFileClip(filename) - video.audio.write_audiofile("audio.wav") - - -def get_file_length(audiofile): - with contextlib.closing(wave.open(audiofile, 'r')) as f: - frames = f.getnframes() - rate = f.getframerate() - duration = frames / float(rate) - return duration - - -def get_text(audiofile="audio.wav"): - r = sr.Recognizer() - audio_length = get_file_length(audiofile) - texts = [] - with sr.AudioFile(audiofile) as source: - for i in range(0, int(round(audio_length / 3))): - try: - text = r.recognize_google(r.record(source, duration=3)) - except sr.UnknownValueError: - text = "error, no sutitles could be distinguished" - texts.append(text) - return texts - - -def write_text(text_chunks, original_video, output, font_size=15): - txt_clips = [] - for i in range(len(text_chunks)): - txt_clips.append(TextClip(text_chunks[i], fontsize=font_size, color="yellow") - .set_position('bottom') - .set_duration(3) - .set_start(i * 3)) - clips = [original_video] - clips.extend(txt_clips) - result = CompositeVideoClip(clips) - result.write_videofile(output) - - -if __name__ == "__main__": - get_audio(sys.argv[1]) - if (len(sys.argv)) > 3: - write_text(get_text(), VideoFileClip(sys.argv[1]), sys.argv[3], sys.argv[1]) - else: - write_text(get_text(), VideoFileClip(sys.argv[1]), sys.argv[2]) +import moviepy.editor as mp +import speech_recognition as sr +import wave +import contextlib +from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip +import sys + + +def get_audio(filename): + video = mp.VideoFileClip(filename) + video.audio.write_audiofile("audio.wav") + + +def get_file_length(audiofile): + with contextlib.closing(wave.open(audiofile, 'r')) as f: + frames = f.getnframes() + rate = f.getframerate() + duration = frames / float(rate) + return duration + + +def get_text(audiofile="audio.wav"): + r = sr.Recognizer() + audio_length = get_file_length(audiofile) + texts = [] + with sr.AudioFile(audiofile) as source: + for i in range(0, int(round(audio_length / 3))): + try: + text = r.recognize_google(r.record(source, duration=3)) + except sr.UnknownValueError: + text = "error, no sutitles could be distinguished" + texts.append(text) + return texts + + +def write_text(text_chunks, original_video, output, font_size=15): + txt_clips = [] + for i in range(len(text_chunks)): + txt_clips.append(TextClip(text_chunks[i], fontsize=font_size, color="yellow") + .set_position('bottom') + .set_duration(3) + .set_start(i * 3)) + clips = [original_video] + clips.extend(txt_clips) + result = CompositeVideoClip(clips) + result.write_videofile(output) + + +if __name__ == "__main__": + get_audio(sys.argv[1]) + if (len(sys.argv)) > 3: + write_text(get_text(), VideoFileClip(sys.argv[1]), sys.argv[3], sys.argv[1]) + else: + write_text(get_text(), VideoFileClip(sys.argv[1]), sys.argv[2]) diff --git a/sudoku_solver/README.md b/sudoku_solver/README.md index ed18666f6..3bd750898 100644 --- a/sudoku_solver/README.md +++ b/sudoku_solver/README.md @@ -1,38 +1,38 @@ -# Sudoku-Solver - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - - If you want a solution for a sudoku puzzle, it may help you. Give each line of the puzzle as input with zeroes in place of spaces. - - This program uses backtracking process to solve. The program finds the zeroes i.e. empty spaces in the line and checks the number in range 9 that it unique in that row , column and square. Like that the code goes on checking each and every space in the puzzle. If any number is repeated inside the row and column, then it is backtrack and changes the number in the respective space. The program uses the recursion to backtrack in the puzzle. - - # Input - 7 8 0 4 0 0 1 2 0 - 6 0 0 0 7 5 0 0 9 - 0 0 0 6 0 1 0 7 8 - 0 0 7 0 4 0 2 6 0 - 0 0 1 0 5 0 9 3 0 - 9 0 4 0 6 0 0 0 5 - 0 7 0 3 0 0 0 1 2 - 1 2 0 0 0 7 4 0 0 - 0 4 9 2 0 6 0 0 7 - - # Output - 7 8 5 | 4 3 9 | 1 2 6 - 6 1 2 | 8 7 5 | 3 4 9 - 4 9 3 | 6 2 1 | 5 7 8 - - - - - - - - - - - - - - - 8 5 7 | 9 4 3 | 2 6 1 - 2 6 1 | 7 5 8 | 9 3 4 - 9 3 4 | 1 6 2 | 7 8 5 - - - - - - - - - - - - - - - 5 7 8 | 3 9 4 | 6 1 2 - 1 2 6 | 5 8 7 | 4 9 3 - 3 4 9 | 2 1 6 | 8 5 7 - Check for more solution? - Thank you +# Sudoku-Solver + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + + If you want a solution for a sudoku puzzle, it may help you. Give each line of the puzzle as input with zeroes in place of spaces. + + This program uses backtracking process to solve. The program finds the zeroes i.e. empty spaces in the line and checks the number in range 9 that it unique in that row , column and square. Like that the code goes on checking each and every space in the puzzle. If any number is repeated inside the row and column, then it is backtrack and changes the number in the respective space. The program uses the recursion to backtrack in the puzzle. + + # Input + 7 8 0 4 0 0 1 2 0 + 6 0 0 0 7 5 0 0 9 + 0 0 0 6 0 1 0 7 8 + 0 0 7 0 4 0 2 6 0 + 0 0 1 0 5 0 9 3 0 + 9 0 4 0 6 0 0 0 5 + 0 7 0 3 0 0 0 1 2 + 1 2 0 0 0 7 4 0 0 + 0 4 9 2 0 6 0 0 7 + + # Output + 7 8 5 | 4 3 9 | 1 2 6 + 6 1 2 | 8 7 5 | 3 4 9 + 4 9 3 | 6 2 1 | 5 7 8 + - - - - - - - - - - - - - + 8 5 7 | 9 4 3 | 2 6 1 + 2 6 1 | 7 5 8 | 9 3 4 + 9 3 4 | 1 6 2 | 7 8 5 + - - - - - - - - - - - - - + 5 7 8 | 3 9 4 | 6 1 2 + 1 2 6 | 5 8 7 | 4 9 3 + 3 4 9 | 2 1 6 | 8 5 7 + Check for more solution? + Thank you diff --git a/sudoku_solver/makefile b/sudoku_solver/makefile index e78e53c81..7aafa604a 100644 --- a/sudoku_solver/makefile +++ b/sudoku_solver/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/text_from_image/README.md b/text_from_image/README.md index 977a230a9..5810af45d 100644 --- a/text_from_image/README.md +++ b/text_from_image/README.md @@ -1,25 +1,25 @@ -# Script to extract text from image - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` -## Libraries used : -opencv-python
-pytesseract
- -## How to use : -``` -pip install opencv-python -pip install tesseract -``` -Just modify the path of files inside the code according to your setup and you're good to go. - -## Possible error : - -raise TesseractNotFoundError()
-pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in your path - -If you get this error, please refer to: https://stackoverflow.com/questions/50655738/how-do-i-resolve-a-tesseractnotfounderror +# Script to extract text from image + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` +## Libraries used : +opencv-python
+pytesseract
+ +## How to use : +``` +pip install opencv-python +pip install tesseract +``` +Just modify the path of files inside the code according to your setup and you're good to go. + +## Possible error : + +raise TesseractNotFoundError()
+pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in your path + +If you get this error, please refer to: https://stackoverflow.com/questions/50655738/how-do-i-resolve-a-tesseractnotfounderror diff --git a/text_summarize/README.md b/text_summarize/README.md index 2f5923073..46eae2a88 100644 --- a/text_summarize/README.md +++ b/text_summarize/README.md @@ -1,32 +1,32 @@ -# Text summarizer - -Summarize the given text - -# Requirements: -pytorch and bert-extractive-summarizer is required as well as all packages required by it. - - -# Usage -text_summarize.py [-h] [-t TEXT] [-f FILE] [-r RATIO] [-o OUTPUT] - -Summarize the given text - -optional arguments: - -h, --help show this help message and exit - -t TEXT, --text TEXT Text to summarize - -f FILE, --file FILE Filename to read text from - -r RATIO, --ratio RATIO - Given the ratio of the summarized text (default: 0.2) - -o OUTPUT, --output OUTPUT - Given the path to an output file. Otherwise stdout - will be used - -# GPU vs CPU -CUDA is used if a gpu is available. To run it on CPU only, use following - -CUDA_VISIBLE_DEVICES='' python3 text_summarize.py [-h] [-t TEXT] [-f FILE] [-r RATIO] [-o OUTPUT] - -With CUDA_VISIBLE_DEVICES='', the GPUs are not visible to python and therefore the CPU is used. - -# Languages +# Text summarizer + +Summarize the given text + +# Requirements: +pytorch and bert-extractive-summarizer is required as well as all packages required by it. + + +# Usage +text_summarize.py [-h] [-t TEXT] [-f FILE] [-r RATIO] [-o OUTPUT] + +Summarize the given text + +optional arguments: + -h, --help show this help message and exit + -t TEXT, --text TEXT Text to summarize + -f FILE, --file FILE Filename to read text from + -r RATIO, --ratio RATIO + Given the ratio of the summarized text (default: 0.2) + -o OUTPUT, --output OUTPUT + Given the path to an output file. Otherwise stdout + will be used + +# GPU vs CPU +CUDA is used if a gpu is available. To run it on CPU only, use following + +CUDA_VISIBLE_DEVICES='' python3 text_summarize.py [-h] [-t TEXT] [-f FILE] [-r RATIO] [-o OUTPUT] + +With CUDA_VISIBLE_DEVICES='', the GPUs are not visible to python and therefore the CPU is used. + +# Languages Currently, only english is supported. \ No newline at end of file diff --git a/text_summarize/requirements.txt b/text_summarize/requirements.txt index 225ea52ed..3f62b89d7 100644 --- a/text_summarize/requirements.txt +++ b/text_summarize/requirements.txt @@ -1,2 +1,2 @@ -torch +torch bert-extractive-summarizer \ No newline at end of file diff --git a/text_summarize/text.txt b/text_summarize/text.txt index 2629f06ab..06ea0b90b 100644 --- a/text_summarize/text.txt +++ b/text_summarize/text.txt @@ -1,22 +1,22 @@ -The Chrysler Building, the famous art deco New York skyscraper, will be sold for a small fraction of its previous sales price. -The deal, first reported by The Real Deal, was for $150 million, according to a source familiar with the deal. -Mubadala, an Abu Dhabi investment fund, purchased 90% of the building for $800 million in 2008. -Real estate firm Tishman Speyer had owned the other 10%. -The buyer is RFR Holding, a New York real estate company. -Officials with Tishman and RFR did not immediately respond to a request for comments. -It's unclear when the deal will close. -The building sold fairly quickly after being publicly placed on the market only two months ago. -The sale was handled by CBRE Group. -The incentive to sell the building at such a huge loss was due to the soaring rent the owners pay to Cooper Union, a New York college, for the land under the building. -The rent is rising from $7.75 million last year to $32.5 million this year to $41 million in 2028. -Meantime, rents in the building itself are not rising nearly that fast. -While the building is an iconic landmark in the New York skyline, it is competing against newer office towers with large floor-to-ceiling windows and all the modern amenities. -Still the building is among the best known in the city, even to people who have never been to New York. -It is famous for its triangle-shaped, vaulted windows worked into the stylized crown, along with its distinctive eagle gargoyles near the top. -It has been featured prominently in many films, including Men in Black 3, Spider-Man, Armageddon, Two Weeks Notice and Independence Day. -The previous sale took place just before the 2008 financial meltdown led to a plunge in real estate prices. -Still there have been a number of high profile skyscrapers purchased for top dollar in recent years, including the Waldorf Astoria hotel, which Chinese firm Anbang Insurance purchased in 2016 for nearly $2 billion, and the Willis Tower in Chicago, which was formerly known as Sears Tower, once the world's tallest. -Blackstone Group (BX) bought it for $1.3 billion 2015. -The Chrysler Building was the headquarters of the American automaker until 1953, but it was named for and owned by Chrysler chief Walter Chrysler, not the company itself. -Walter Chrysler had set out to build the tallest building in the world, a competition at that time with another Manhattan skyscraper under construction at 40 Wall Street at the south end of Manhattan. He kept secret the plans for the spire that would grace the top of the building, building it inside the structure and out of view of the public until 40 Wall Street was complete. -Once the competitor could rise no higher, the spire of the Chrysler building was raised into view, giving it the title. +The Chrysler Building, the famous art deco New York skyscraper, will be sold for a small fraction of its previous sales price. +The deal, first reported by The Real Deal, was for $150 million, according to a source familiar with the deal. +Mubadala, an Abu Dhabi investment fund, purchased 90% of the building for $800 million in 2008. +Real estate firm Tishman Speyer had owned the other 10%. +The buyer is RFR Holding, a New York real estate company. +Officials with Tishman and RFR did not immediately respond to a request for comments. +It's unclear when the deal will close. +The building sold fairly quickly after being publicly placed on the market only two months ago. +The sale was handled by CBRE Group. +The incentive to sell the building at such a huge loss was due to the soaring rent the owners pay to Cooper Union, a New York college, for the land under the building. +The rent is rising from $7.75 million last year to $32.5 million this year to $41 million in 2028. +Meantime, rents in the building itself are not rising nearly that fast. +While the building is an iconic landmark in the New York skyline, it is competing against newer office towers with large floor-to-ceiling windows and all the modern amenities. +Still the building is among the best known in the city, even to people who have never been to New York. +It is famous for its triangle-shaped, vaulted windows worked into the stylized crown, along with its distinctive eagle gargoyles near the top. +It has been featured prominently in many films, including Men in Black 3, Spider-Man, Armageddon, Two Weeks Notice and Independence Day. +The previous sale took place just before the 2008 financial meltdown led to a plunge in real estate prices. +Still there have been a number of high profile skyscrapers purchased for top dollar in recent years, including the Waldorf Astoria hotel, which Chinese firm Anbang Insurance purchased in 2016 for nearly $2 billion, and the Willis Tower in Chicago, which was formerly known as Sears Tower, once the world's tallest. +Blackstone Group (BX) bought it for $1.3 billion 2015. +The Chrysler Building was the headquarters of the American automaker until 1953, but it was named for and owned by Chrysler chief Walter Chrysler, not the company itself. +Walter Chrysler had set out to build the tallest building in the world, a competition at that time with another Manhattan skyscraper under construction at 40 Wall Street at the south end of Manhattan. He kept secret the plans for the spire that would grace the top of the building, building it inside the structure and out of view of the public until 40 Wall Street was complete. +Once the competitor could rise no higher, the spire of the Chrysler building was raised into view, giving it the title. diff --git a/text_summarize/text_summarize.py b/text_summarize/text_summarize.py index 70fb63c14..2f493145d 100644 --- a/text_summarize/text_summarize.py +++ b/text_summarize/text_summarize.py @@ -1,49 +1,49 @@ -import argparse -from summarizer import Summarizer - - -def text_summarize(text, **kwargs): - """ - Summarize the given text. Returns the summarize - """ - model = Summarizer() - return model(text, **kwargs) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - description='Summarize the given text') - parser.add_argument('-t', '--text', help="Text to summarize", - type=str) - parser.add_argument('-f', '--file', help="Filename to read text from", - type=str) - parser.add_argument('-r', '--ratio', - help="Given the ratio of the summarized text " - "(default: 0.2)", - type=float, default=0.2) - parser.add_argument('-o', '--output', - help="Given the path to an output file. " - "Otherwise stdout will be used", - type=str, default=None) - args = parser.parse_args() - - if not (args.text or args.file): - parser.error("Either --text or --file is required") - if args.text and args.file: - parser.error("The arguments --text and --file are not " - "allowed together") - - if args.file: - with open(args.file, 'r') as infile: - text = infile.readlines() - text = "\n".join(text) - if args.text: - text = args.text - - summary = text_summarize(text, ratio=args.ratio) - if args.output: - with open(args.output, 'w') as outfile: - outfile.write(summary) - outfile.write("\n") - else: - print(summary) +import argparse +from summarizer import Summarizer + + +def text_summarize(text, **kwargs): + """ + Summarize the given text. Returns the summarize + """ + model = Summarizer() + return model(text, **kwargs) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='Summarize the given text') + parser.add_argument('-t', '--text', help="Text to summarize", + type=str) + parser.add_argument('-f', '--file', help="Filename to read text from", + type=str) + parser.add_argument('-r', '--ratio', + help="Given the ratio of the summarized text " + "(default: 0.2)", + type=float, default=0.2) + parser.add_argument('-o', '--output', + help="Given the path to an output file. " + "Otherwise stdout will be used", + type=str, default=None) + args = parser.parse_args() + + if not (args.text or args.file): + parser.error("Either --text or --file is required") + if args.text and args.file: + parser.error("The arguments --text and --file are not " + "allowed together") + + if args.file: + with open(args.file, 'r') as infile: + text = infile.readlines() + text = "\n".join(text) + if args.text: + text = args.text + + summary = text_summarize(text, ratio=args.ratio) + if args.output: + with open(args.output, 'w') as outfile: + outfile.write(summary) + outfile.write("\n") + else: + print(summary) diff --git a/text_to_sound/README.md b/text_to_sound/README.md index 2e85df24b..b3ca9502c 100644 --- a/text_to_sound/README.md +++ b/text_to_sound/README.md @@ -1,33 +1,33 @@ -# Converting Text to Speech By Python - -This script involves implementation of Google text to speech API which is deployed on Deep Learning Algorithm Wavenet . The API is used for a better usability and simple architecture of the script , so that everyone can use it . It involves playsound (for audio files) . The steps how to use the script as well the visuals are shown below : - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## Install Dependencies manually: - -``` -python run requirements.txt (will install all dependienies in your local operating system) -``` -There will be some command issues regarding Anaconda usgae it is cited below : -``` -If using anaconda , then follow the steps : -Step 1 : Open Anaconda Power Shell -Step 2 : pip install gTTS -Step 3 : pip install playsound -``` -If you want to use Anaconda as a virtual environment then : -``` -1.) Step 1 : Open Anaconda Cmd prompt -2.) Step 2 : conda create --name pip_env -3.) Step 3 : conda activate pip_env -4.) Step 4 : conda install pip -5.) Step 5 : Now you can use above commands -``` -Visuals of the code bases and the interface is there in the Assets folder , -Simply Run the script and the interface will open , and start converting your text to speech. +# Converting Text to Speech By Python + +This script involves implementation of Google text to speech API which is deployed on Deep Learning Algorithm Wavenet . The API is used for a better usability and simple architecture of the script , so that everyone can use it . It involves playsound (for audio files) . The steps how to use the script as well the visuals are shown below : + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## Install Dependencies manually: + +``` +python run requirements.txt (will install all dependienies in your local operating system) +``` +There will be some command issues regarding Anaconda usgae it is cited below : +``` +If using anaconda , then follow the steps : +Step 1 : Open Anaconda Power Shell +Step 2 : pip install gTTS +Step 3 : pip install playsound +``` +If you want to use Anaconda as a virtual environment then : +``` +1.) Step 1 : Open Anaconda Cmd prompt +2.) Step 2 : conda create --name pip_env +3.) Step 3 : conda activate pip_env +4.) Step 4 : conda install pip +5.) Step 5 : Now you can use above commands +``` +Visuals of the code bases and the interface is there in the Assets folder , +Simply Run the script and the interface will open , and start converting your text to speech. diff --git a/text_to_sound/makefile b/text_to_sound/makefile index e78e53c81..7aafa604a 100644 --- a/text_to_sound/makefile +++ b/text_to_sound/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/text_to_sound/requirements.txt b/text_to_sound/requirements.txt index f6934beed..d5af933f8 100644 --- a/text_to_sound/requirements.txt +++ b/text_to_sound/requirements.txt @@ -1,3 +1,3 @@ -playsound = 1.2.2 -tkinter = 0.13.0 -gTTS = 2.1.1 +playsound = 1.2.2 +tkinter = 0.13.0 +gTTS = 2.1.1 diff --git a/text_to_sound/text_to_sound.py b/text_to_sound/text_to_sound.py index 32857ae1c..0c1d04081 100644 --- a/text_to_sound/text_to_sound.py +++ b/text_to_sound/text_to_sound.py @@ -1,7 +1,7 @@ -from gtts import gTTS -from playsound import playsound -text_val = 'All the best for your exam.' -language = 'en' -obj = gTTS(text=text_val, lang=language, slow=False) -obj.save("exam.mp3") -playsound("exam.mp3") +from gtts import gTTS +from playsound import playsound +text_val = 'All the best for your exam.' +language = 'en' +obj = gTTS(text=text_val, lang=language, slow=False) +obj.save("exam.mp3") +playsound("exam.mp3") diff --git a/todo_list/README.md b/todo_list/README.md index 541e1b9b8..a7c3dbbd8 100644 --- a/todo_list/README.md +++ b/todo_list/README.md @@ -1,16 +1,16 @@ -# To-Do List -A to-do list application made using Python's flask framework - -## Setup virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -# Usage -Run the script in the terminal and access http://localhost:5000 in your web browser to view the application - -# Requirements -- setup virtual environment or install requirements manually -- install sqlite if required +# To-Do List +A to-do list application made using Python's flask framework + +## Setup virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +# Usage +Run the script in the terminal and access http://localhost:5000 in your web browser to view the application + +# Requirements +- setup virtual environment or install requirements manually +- install sqlite if required diff --git a/todo_list/app.py b/todo_list/app.py index 310807b10..d30c9236b 100644 --- a/todo_list/app.py +++ b/todo_list/app.py @@ -1,70 +1,70 @@ -from flask import Flask, render_template, request, flash, redirect -from flask_sqlalchemy import SQLAlchemy -from datetime import datetime - -app = Flask(__name__) -app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' -app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -app.secret_key = 'any random secret' -db = SQLAlchemy(app) - - -class TODO(db.Model): - id = db.Column(db.Integer, primary_key=True) - content = db.Column(db.String(200), nullable=False) - date_created = db.Column(db.DateTime, default=datetime.utcnow) - - def __repr__(self): - return '' % self.id - - -@app.route('/', methods=['POST', 'GET']) -def hello(): - db.create_all() - if request.method == 'POST': - task = request.form['content'] - new_task = TODO(content=task) - try: - db.session.add(new_task) - db.session.commit() - flash('Successfully added!') - return redirect('/') - except Exception: - flash('An error occurred') - return redirect('/') - else: - tasks = TODO.query.order_by(TODO.date_created).all() - return render_template("toDoListTemplate.html", tasks=tasks) - - -@app.route('/delete/') -def delete(id): - task = TODO.query.get_or_404(id) - try: - db.session.delete(task) - db.session.commit() - flash('Successfully deleted') - return redirect('/') - except Exception: - flash('An error occurred') - return redirect('/') - - -@app.route('/modify/', methods=['POST', 'GET']) -def modify(id): - task = TODO.query.get_or_404(id) - if request.method == 'POST': - task.content = request.form['content'] - try: - db.session.commit() - flash("Successfully updated") - return redirect('/') - except Exception: - flash("An error occurred") - return redirect('/') - else: - return render_template("toDoListTemplate.html", tasks=task) - - -if __name__ == '__main__': - app.run(debug=True) +from flask import Flask, render_template, request, flash, redirect +from flask_sqlalchemy import SQLAlchemy +from datetime import datetime + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.secret_key = 'any random secret' +db = SQLAlchemy(app) + + +class TODO(db.Model): + id = db.Column(db.Integer, primary_key=True) + content = db.Column(db.String(200), nullable=False) + date_created = db.Column(db.DateTime, default=datetime.utcnow) + + def __repr__(self): + return '' % self.id + + +@app.route('/', methods=['POST', 'GET']) +def hello(): + db.create_all() + if request.method == 'POST': + task = request.form['content'] + new_task = TODO(content=task) + try: + db.session.add(new_task) + db.session.commit() + flash('Successfully added!') + return redirect('/') + except Exception: + flash('An error occurred') + return redirect('/') + else: + tasks = TODO.query.order_by(TODO.date_created).all() + return render_template("toDoListTemplate.html", tasks=tasks) + + +@app.route('/delete/') +def delete(id): + task = TODO.query.get_or_404(id) + try: + db.session.delete(task) + db.session.commit() + flash('Successfully deleted') + return redirect('/') + except Exception: + flash('An error occurred') + return redirect('/') + + +@app.route('/modify/', methods=['POST', 'GET']) +def modify(id): + task = TODO.query.get_or_404(id) + if request.method == 'POST': + task.content = request.form['content'] + try: + db.session.commit() + flash("Successfully updated") + return redirect('/') + except Exception: + flash("An error occurred") + return redirect('/') + else: + return render_template("toDoListTemplate.html", tasks=task) + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/todo_list/makefile b/todo_list/makefile index e78e53c81..7aafa604a 100644 --- a/todo_list/makefile +++ b/todo_list/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/todo_list/requirements.txt b/todo_list/requirements.txt index de8a130b9..bc8802dec 100644 --- a/todo_list/requirements.txt +++ b/todo_list/requirements.txt @@ -1,2 +1,2 @@ -flask -flask_sqlalchemy +flask +flask_sqlalchemy diff --git a/todo_list/static/styles.css b/todo_list/static/styles.css index ea478413e..9c97ea337 100644 --- a/todo_list/static/styles.css +++ b/todo_list/static/styles.css @@ -1,19 +1,19 @@ -.content{ - text-align: center; - display: inline-block; - overflow-x: auto; -} -body{ - font-family:Abel; - text-align: center; - background-color:azure; -} -#modifyTask{ - text-align:left; -} -a:link { - color: blue; -} -a:visited{ - color: blue; -} +.content{ + text-align: center; + display: inline-block; + overflow-x: auto; +} +body{ + font-family:Abel; + text-align: center; + background-color:azure; +} +#modifyTask{ + text-align:left; +} +a:link { + color: blue; +} +a:visited{ + color: blue; +} diff --git a/todo_list/templates/toDoListTemplate.html b/todo_list/templates/toDoListTemplate.html index 9c40575fa..876854e5f 100644 --- a/todo_list/templates/toDoListTemplate.html +++ b/todo_list/templates/toDoListTemplate.html @@ -1,91 +1,91 @@ - - - - {% block head %} - - - - - - - - {% endblock %} - - - {% block body %} -
- {% with msg=get_flashed_messages() %} - {% if msg %} - {% for message in msg %} - {{ message }} -
- {% endfor %} - {% endif %} - {% endwith %} -

To-Do List

-
-
- - -
-
- - {% if tasks %} - - - - - - {% for task in tasks %} - - - - - - - {% endfor %} - {% else %} - No items in list - {% endif %} -
Task Added Actions
{{ task.content }} {{ task.date_created.date() }} - Delete -
- Update -
-
-
-
- - {% endblock %} - - + + + + {% block head %} + + + + + + + + {% endblock %} + + + {% block body %} +
+ {% with msg=get_flashed_messages() %} + {% if msg %} + {% for message in msg %} + {{ message }} +
+ {% endfor %} + {% endif %} + {% endwith %} +

To-Do List

+
+
+ + +
+
+ + {% if tasks %} + + + + + + {% for task in tasks %} + + + + + + + {% endfor %} + {% else %} + No items in list + {% endif %} +
Task Added Actions
{{ task.content }} {{ task.date_created.date() }} + Delete +
+ Update +
+
+
+
+ + {% endblock %} + + diff --git a/torrent_search/LICENSE b/torrent_search/LICENSE index 18c645adf..b0b25ec8b 100644 --- a/torrent_search/LICENSE +++ b/torrent_search/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2020 Holger DΓΆrner - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +MIT License + +Copyright (c) 2020 Holger DΓΆrner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/torrent_search/README.md b/torrent_search/README.md index d46a07349..2a5c0be8d 100644 --- a/torrent_search/README.md +++ b/torrent_search/README.md @@ -1,47 +1,47 @@ -# torrent_search.py -A torrent-meta-searcher - -This script searches (scrapes) on multiple Torrent sites for supplied keywords and returns the results grouped by categories as `JSON`. - -Currently, the following sites are queried: -- thepiratebay10.org -- 1337x.to -- torlock.com - -## Requirements and Dependencies -Recommendet Python-Version -- `3.5+` - -The only external dependency are -- `BeautifulSoap` -- `aiohttp` - -## Installation -Install the required external dependencies with - -```shell -$ pip3 install -r requirements.txt -``` - -Also, a `chmod +x torrent_search.py` *can* be needed to make the script executable, otherwise You have to call it with `python3` (see [Usage Examples](#usage-examples)) - -## Usage examples -Getting help: -```shell -$ (python3) torrent_search.py -h -``` - -Perform a simple search: -```shell -$ (python3) torrent_search.py doom -``` - -Filter results with at least 20 seeders for `big bang theory`: -```shell -$ (python3) torrent_search.py "big bang theory" -s 20 -``` - -Filter by categories: -```shell -$ (python3) torrent_search.py doom -c Movies Games -``` +# torrent_search.py +A torrent-meta-searcher + +This script searches (scrapes) on multiple Torrent sites for supplied keywords and returns the results grouped by categories as `JSON`. + +Currently, the following sites are queried: +- thepiratebay10.org +- 1337x.to +- torlock.com + +## Requirements and Dependencies +Recommendet Python-Version +- `3.5+` + +The only external dependency are +- `BeautifulSoap` +- `aiohttp` + +## Installation +Install the required external dependencies with + +```shell +$ pip3 install -r requirements.txt +``` + +Also, a `chmod +x torrent_search.py` *can* be needed to make the script executable, otherwise You have to call it with `python3` (see [Usage Examples](#usage-examples)) + +## Usage examples +Getting help: +```shell +$ (python3) torrent_search.py -h +``` + +Perform a simple search: +```shell +$ (python3) torrent_search.py doom +``` + +Filter results with at least 20 seeders for `big bang theory`: +```shell +$ (python3) torrent_search.py "big bang theory" -s 20 +``` + +Filter by categories: +```shell +$ (python3) torrent_search.py doom -c Movies Games +``` diff --git a/torrent_search/requirements.txt b/torrent_search/requirements.txt index fc9b498e7..2b4383f7f 100644 --- a/torrent_search/requirements.txt +++ b/torrent_search/requirements.txt @@ -1,2 +1,2 @@ -BeautifulSoup4 +BeautifulSoup4 aiohttp \ No newline at end of file diff --git a/torrent_search/torrent_search.py b/torrent_search/torrent_search.py index 29e56eb58..b3701cc81 100755 --- a/torrent_search/torrent_search.py +++ b/torrent_search/torrent_search.py @@ -1,306 +1,306 @@ -#!/usr/bin/env python3 - -import asyncio -import json -import argparse -from aiohttp import ClientSession, ClientError -from aiohttp.http_exceptions import HttpProcessingError -from urllib.parse import quote -from collections import defaultdict -from re import sub -from bs4 import BeautifulSoup - -results = defaultdict(list) - -urlList = { - 'thepiratebay': 'https://thepiratebay10.org/search/{query}/{page}/99/0', - '1337x': 'https://1337x.to/search/{query}/{page}/', - 'torlock': 'https://www.torlock.com/all/torrents/{query}/{page}.html' -} - -category_list = { - 'anime': 'Anime', - 'applications': 'Applications', - 'documentaries': 'Documentaries', - 'games': 'Games', - 'movies': 'Movies', - 'music': 'Music', - 'other': 'Other', - 'television': 'Television', - 'xxx': 'XXX', - 'unknown': 'Unknown' -} - - -def to_object( - title: str = '', - url: str = '', - magnet_link: str = '', - seeder: int = None, - leecher: int = None -): - return { - 'title': title, - 'url': url, - 'magett-link': magnet_link, - 'seeder': seeder, - 'leecher': leecher - } - - -def parse_args() -> argparse.Namespace: - parser = argparse.ArgumentParser( - description='Meta-Search-Script for torrents.' - ) - parser.add_argument('query', metavar='QUERY', type=str, - help='the search term') - parser.add_argument('-s', '--seeder-limit', dest='seeder_limit', type=int, - action='store', default=0, - help='minimum number of seeders') - parser.add_argument('-c', '--categories', dest='categories', - nargs='*', default=[], - help='filter by categories') - - args = parser.parse_args() - - for i in range(len(args.categories)): - args.categories[i] = args.categories[i].casefold() - - return args - - -async def send_query( - url: str, - session: ClientSession, - headers: dict = None -) -> str: - response = await session.request(method='GET', url=url, headers=headers) - response.raise_for_status() - return await response.text(errors='ignore') - - -async def parse_thepiratebay( - args: argparse.Namespace, - session: ClientSession -) -> None: - page = 1 - - while (True): - try: - html = await send_query(urlList['thepiratebay'].format_map({ - 'query': quote(args.query), - 'page': page}), - session - ) - except (ClientError, HttpProcessingError): - break - - soup = BeautifulSoup(html, 'html.parser') - - try: - rows = soup.find('div', id='main-content').find_all('tr')[1:-1] - except AttributeError: - break - - if len(rows) == 0: - break - - for row in rows: - columns = row.find_all('td') - category = sub(r'\W+', ' ', columns[0].find('a').text).strip() - category = category_list.get( - category.lower(), - category_list.get('unknown') - ) - title = sub( - '[\n\t]+', - ' ', - columns[1].find('div', class_='detName').text - ).strip() - url = columns[1].find('a', href=True)['href'] - magnet_link = columns[1].find_all('a')[1]['href'] - seeder = int(columns[2].text.strip()) - leecher = int(columns[3].text.strip()) - - if len(args.categories) > 0: - if category.casefold() not in args.categories: - continue - - if seeder < args.seeder_limit: - continue - - results[category].append(to_object( - title=title, - url=url, - magnet_link=magnet_link, - seeder=seeder, - leecher=leecher - )) - - page += 1 - - -async def parse_1337x( - args: argparse.Namespace, - session: ClientSession -) -> None: - category_mappings = { - '6': category_list.get('television'), - '9': category_list.get('documentaries'), - '10': category_list.get('games'), - '18': category_list.get('applications'), - '19': category_list.get('applications'), - '22': category_list.get('music'), - '23': category_list.get('music'), - '28': category_list.get('anime'), - '36': category_list.get('other'), - '41': category_list.get('television'), - '42': category_list.get('movies'), - '48': category_list.get('xxx'), - '50': category_list.get('other'), - '51': category_list.get('xxx'), - '52': category_list.get('other'), - '53': category_list.get('music'), - '56': category_list.get('applications'), - '59': category_list.get('music'), - '71': category_list.get('television'), - '75': category_list.get('television'), - '78': category_list.get('anime'), - '80': category_list.get('anime'), - } - - page = 1 - - while (True): - try: - html = await send_query(urlList['1337x'].format_map({ - 'query': quote(args.query), - 'page': page}), - session - ) - except (ClientError, HttpProcessingError): - break - - soup = BeautifulSoup(html, 'html.parser') - - try: - rows = soup.find('table', class_='table-list').find_all('tr')[1:] - except AttributeError: - break - - if len(rows) == 0: - break - - for row in rows: - columns = row.find_all('td') - category = columns[0].find_all('a')[0]['href'].split('/')[2] - category = category_mappings.get( - category, - category_list.get('unknown') - ) - title = columns[0].find_all('a')[1].text.strip() - url = 'https://1337x.to' + columns[0].find_all('a')[1]['href'] - seeder = int(columns[1].text.strip()) - leecher = int(columns[2].text.strip()) - - if len(args.categories) > 0: - if category.casefold() not in args.categories: - continue - - if seeder < args.seeder_limit: - continue - - results[category].append(to_object( - title=title, - url=url, - seeder=seeder, - leecher=leecher - )) - - page += 1 - - -async def parse_torlock(args, session: ClientSession) -> None: - category_mappings = { - 'tv0': category_list.get('other'), - 'tv1': category_list.get('movie'), - 'tv2': category_list.get('music'), - 'tv3': category_list.get('television'), - 'tv4': category_list.get('games'), - 'tv5': category_list.get('application'), - 'tv6': category_list.get('anime'), - 'tv7': category_list.get('xxx'), - 'tv8': category_list.get('other'), - 'tv9': category_list.get('other'), - 'tv10': category_list.get('television'), - 'tv12': category_list.get('other') - } - - page = 1 - - while (True): - try: - html = await send_query(urlList['torlock'].format_map({ - 'query': quote(args.query), - 'page': page}), - session - ) - except (ClientError, HttpProcessingError): - break - - soup = BeautifulSoup(html, 'html.parser') - - try: - rows = soup.find_all('table')[4].find_all('tr')[1:] - except AttributeError: - break - - if len(rows) == 0: - break - - for row in rows: - columns = row.find_all('td') - category = columns[0].find('span')['class'][0] - category = category_mappings.get( - category, - category_list.get('unknown') - ) - title = columns[0].find('a').text.strip() - url = 'https://torlock.to' + columns[0].find('a')['href'] - seeder = int(columns[3].text.strip()) - leecher = int(columns[4].text.strip()) - - if len(args.categories) > 0: - if category.casefold() not in args.categories: - continue - - if seeder < args.seeder_limit: - continue - - results[category].append(to_object( - title=title, - url=url, - seeder=seeder, - leecher=leecher - )) - - page += 1 - - -async def run(args): - task_list = [ - parse_thepiratebay, - parse_1337x, - parse_torlock - ] - - async with ClientSession() as session: - for i in range(len(task_list)): - task_list[i] = task_list[i](args, session) - await asyncio.gather(*task_list) - - -if __name__ == "__main__": - args = parse_args() - asyncio.run(run(args)) - print(json.dumps(results, indent=4)) +#!/usr/bin/env python3 + +import asyncio +import json +import argparse +from aiohttp import ClientSession, ClientError +from aiohttp.http_exceptions import HttpProcessingError +from urllib.parse import quote +from collections import defaultdict +from re import sub +from bs4 import BeautifulSoup + +results = defaultdict(list) + +urlList = { + 'thepiratebay': 'https://thepiratebay10.org/search/{query}/{page}/99/0', + '1337x': 'https://1337x.to/search/{query}/{page}/', + 'torlock': 'https://www.torlock.com/all/torrents/{query}/{page}.html' +} + +category_list = { + 'anime': 'Anime', + 'applications': 'Applications', + 'documentaries': 'Documentaries', + 'games': 'Games', + 'movies': 'Movies', + 'music': 'Music', + 'other': 'Other', + 'television': 'Television', + 'xxx': 'XXX', + 'unknown': 'Unknown' +} + + +def to_object( + title: str = '', + url: str = '', + magnet_link: str = '', + seeder: int = None, + leecher: int = None +): + return { + 'title': title, + 'url': url, + 'magett-link': magnet_link, + 'seeder': seeder, + 'leecher': leecher + } + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description='Meta-Search-Script for torrents.' + ) + parser.add_argument('query', metavar='QUERY', type=str, + help='the search term') + parser.add_argument('-s', '--seeder-limit', dest='seeder_limit', type=int, + action='store', default=0, + help='minimum number of seeders') + parser.add_argument('-c', '--categories', dest='categories', + nargs='*', default=[], + help='filter by categories') + + args = parser.parse_args() + + for i in range(len(args.categories)): + args.categories[i] = args.categories[i].casefold() + + return args + + +async def send_query( + url: str, + session: ClientSession, + headers: dict = None +) -> str: + response = await session.request(method='GET', url=url, headers=headers) + response.raise_for_status() + return await response.text(errors='ignore') + + +async def parse_thepiratebay( + args: argparse.Namespace, + session: ClientSession +) -> None: + page = 1 + + while (True): + try: + html = await send_query(urlList['thepiratebay'].format_map({ + 'query': quote(args.query), + 'page': page}), + session + ) + except (ClientError, HttpProcessingError): + break + + soup = BeautifulSoup(html, 'html.parser') + + try: + rows = soup.find('div', id='main-content').find_all('tr')[1:-1] + except AttributeError: + break + + if len(rows) == 0: + break + + for row in rows: + columns = row.find_all('td') + category = sub(r'\W+', ' ', columns[0].find('a').text).strip() + category = category_list.get( + category.lower(), + category_list.get('unknown') + ) + title = sub( + '[\n\t]+', + ' ', + columns[1].find('div', class_='detName').text + ).strip() + url = columns[1].find('a', href=True)['href'] + magnet_link = columns[1].find_all('a')[1]['href'] + seeder = int(columns[2].text.strip()) + leecher = int(columns[3].text.strip()) + + if len(args.categories) > 0: + if category.casefold() not in args.categories: + continue + + if seeder < args.seeder_limit: + continue + + results[category].append(to_object( + title=title, + url=url, + magnet_link=magnet_link, + seeder=seeder, + leecher=leecher + )) + + page += 1 + + +async def parse_1337x( + args: argparse.Namespace, + session: ClientSession +) -> None: + category_mappings = { + '6': category_list.get('television'), + '9': category_list.get('documentaries'), + '10': category_list.get('games'), + '18': category_list.get('applications'), + '19': category_list.get('applications'), + '22': category_list.get('music'), + '23': category_list.get('music'), + '28': category_list.get('anime'), + '36': category_list.get('other'), + '41': category_list.get('television'), + '42': category_list.get('movies'), + '48': category_list.get('xxx'), + '50': category_list.get('other'), + '51': category_list.get('xxx'), + '52': category_list.get('other'), + '53': category_list.get('music'), + '56': category_list.get('applications'), + '59': category_list.get('music'), + '71': category_list.get('television'), + '75': category_list.get('television'), + '78': category_list.get('anime'), + '80': category_list.get('anime'), + } + + page = 1 + + while (True): + try: + html = await send_query(urlList['1337x'].format_map({ + 'query': quote(args.query), + 'page': page}), + session + ) + except (ClientError, HttpProcessingError): + break + + soup = BeautifulSoup(html, 'html.parser') + + try: + rows = soup.find('table', class_='table-list').find_all('tr')[1:] + except AttributeError: + break + + if len(rows) == 0: + break + + for row in rows: + columns = row.find_all('td') + category = columns[0].find_all('a')[0]['href'].split('/')[2] + category = category_mappings.get( + category, + category_list.get('unknown') + ) + title = columns[0].find_all('a')[1].text.strip() + url = 'https://1337x.to' + columns[0].find_all('a')[1]['href'] + seeder = int(columns[1].text.strip()) + leecher = int(columns[2].text.strip()) + + if len(args.categories) > 0: + if category.casefold() not in args.categories: + continue + + if seeder < args.seeder_limit: + continue + + results[category].append(to_object( + title=title, + url=url, + seeder=seeder, + leecher=leecher + )) + + page += 1 + + +async def parse_torlock(args, session: ClientSession) -> None: + category_mappings = { + 'tv0': category_list.get('other'), + 'tv1': category_list.get('movie'), + 'tv2': category_list.get('music'), + 'tv3': category_list.get('television'), + 'tv4': category_list.get('games'), + 'tv5': category_list.get('application'), + 'tv6': category_list.get('anime'), + 'tv7': category_list.get('xxx'), + 'tv8': category_list.get('other'), + 'tv9': category_list.get('other'), + 'tv10': category_list.get('television'), + 'tv12': category_list.get('other') + } + + page = 1 + + while (True): + try: + html = await send_query(urlList['torlock'].format_map({ + 'query': quote(args.query), + 'page': page}), + session + ) + except (ClientError, HttpProcessingError): + break + + soup = BeautifulSoup(html, 'html.parser') + + try: + rows = soup.find_all('table')[4].find_all('tr')[1:] + except AttributeError: + break + + if len(rows) == 0: + break + + for row in rows: + columns = row.find_all('td') + category = columns[0].find('span')['class'][0] + category = category_mappings.get( + category, + category_list.get('unknown') + ) + title = columns[0].find('a').text.strip() + url = 'https://torlock.to' + columns[0].find('a')['href'] + seeder = int(columns[3].text.strip()) + leecher = int(columns[4].text.strip()) + + if len(args.categories) > 0: + if category.casefold() not in args.categories: + continue + + if seeder < args.seeder_limit: + continue + + results[category].append(to_object( + title=title, + url=url, + seeder=seeder, + leecher=leecher + )) + + page += 1 + + +async def run(args): + task_list = [ + parse_thepiratebay, + parse_1337x, + parse_torlock + ] + + async with ClientSession() as session: + for i in range(len(task_list)): + task_list[i] = task_list[i](args, session) + await asyncio.gather(*task_list) + + +if __name__ == "__main__": + args = parse_args() + asyncio.run(run(args)) + print(json.dumps(results, indent=4)) diff --git a/tweet_bot/Dockerfile b/tweet_bot/Dockerfile index 7e2854e7e..1e909bad3 100644 --- a/tweet_bot/Dockerfile +++ b/tweet_bot/Dockerfile @@ -1,9 +1,9 @@ -FROM python:3.7-alpine - -COPY config.py /app/ -COPY favretweet.py /app/ -COPY requirements.txt /tmp -RUN pip3 install -r /tmp/requirements.txt - -WORKDIR /app -CMD ["python3", "favretweet.py"] +FROM python:3.7-alpine + +COPY config.py /app/ +COPY favretweet.py /app/ +COPY requirements.txt /tmp +RUN pip3 install -r /tmp/requirements.txt + +WORKDIR /app +CMD ["python3", "favretweet.py"] diff --git a/tweet_bot/README.md b/tweet_bot/README.md index 6476fdf1d..dd64e609a 100644 --- a/tweet_bot/README.md +++ b/tweet_bot/README.md @@ -1,74 +1,74 @@ -# TWEETBOT - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -### Objectives -- [x] Follow Followers - followfollowers.py - - automatically follows anyone who follows you. -- [x] (F)ave star and retweet - favretweet.py - - automatically likes and retweets tweets that match certain criteria. - -- [ ] Autoreply - nlp Knowledge needed -- [x] tweet-cli - Ongoing - - -### Requirements -* Developer's API cerdential. Please visit [Twitter Developer Site](https://developer.twitter.com/) -* Python -* Docker Engine - -## Directory Structure - -``` -β”œβ”€β”€ Dockerfile -β”œβ”€β”€ requirements.txt -β”œβ”€β”€ config.py -β”œβ”€β”€ favretweet.py -└── followfollowers.py -``` - -### USAGE: - -#### Using Local/Remote machine: -This is compatible with Linux and OSx -``` -$ make init -$ export CONSUMER_KEY="" -$ export CONSUMER_SECRET="" -$ export ACCESS_TOKEN="" -$ export ACCESS_TOKEN_SECRET="" -$ source .venv/bin/activate # if pyenv is in use -$ python followfollowers.py # or faveretweet.py -``` - -###### Using tweet-cli in local machine - -``` -$ chomd +x tweet-cli.py -$ ln -s tweet-cli.py /usr/local/bin/tweet-cli -$ tweet-cli "this is my tweet from tweet-cli" -``` - -#### Using Docker-Container - -##### Build the Docker Image -``` -docker build -t fav-retweet-bot . -``` -##### Run the Docker Image -``` -docker run -it -e CONSUMER_KEY="" \ - -e CONSUMER_SECRET="" \ - -e ACCESS_TOKEN="" \ - -e ACCESS_TOKEN_SECRET="" \ - fav-retweet-bot -``` - +# TWEETBOT + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +### Objectives +- [x] Follow Followers - followfollowers.py + + automatically follows anyone who follows you. +- [x] (F)ave star and retweet - favretweet.py + + automatically likes and retweets tweets that match certain criteria. + +- [ ] Autoreply - nlp Knowledge needed +- [x] tweet-cli - Ongoing + + +### Requirements +* Developer's API cerdential. Please visit [Twitter Developer Site](https://developer.twitter.com/) +* Python +* Docker Engine + +## Directory Structure + +``` +β”œβ”€β”€ Dockerfile +β”œβ”€β”€ requirements.txt +β”œβ”€β”€ config.py +β”œβ”€β”€ favretweet.py +└── followfollowers.py +``` + +### USAGE: + +#### Using Local/Remote machine: +This is compatible with Linux and OSx +``` +$ make init +$ export CONSUMER_KEY="" +$ export CONSUMER_SECRET="" +$ export ACCESS_TOKEN="" +$ export ACCESS_TOKEN_SECRET="" +$ source .venv/bin/activate # if pyenv is in use +$ python followfollowers.py # or faveretweet.py +``` + +###### Using tweet-cli in local machine + +``` +$ chomd +x tweet-cli.py +$ ln -s tweet-cli.py /usr/local/bin/tweet-cli +$ tweet-cli "this is my tweet from tweet-cli" +``` + +#### Using Docker-Container + +##### Build the Docker Image +``` +docker build -t fav-retweet-bot . +``` +##### Run the Docker Image +``` +docker run -it -e CONSUMER_KEY="" \ + -e CONSUMER_SECRET="" \ + -e ACCESS_TOKEN="" \ + -e ACCESS_TOKEN_SECRET="" \ + fav-retweet-bot +``` + suggestions: Please open an issue and tag me @ashkankamyab \ No newline at end of file diff --git a/tweet_bot/config.py b/tweet_bot/config.py index 4aecb3140..4c1617e43 100644 --- a/tweet_bot/config.py +++ b/tweet_bot/config.py @@ -1,24 +1,24 @@ -#!/usr/bin/env python3 -import tweepy -import logging -import os - -logger = logging.getLogger() - - -def create_api(): - consumer_key = os.getenv("CONSUMER_KEY") - consumer_secret = os.getenv("CONSUMER_SECRET") - access_token = os.getenv("ACCESS_TOKEN") - access_token_secret = os.getenv("ACCESS_TOKEN_SECRET") - - auth = tweepy.OAuthHandler(consumer_key, consumer_secret) - auth.set_access_token(access_token, access_token_secret) - api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True) - try: - api.verify_credentials() - except Exception as e: - logger.error("Error creating API", exc_info=True) - raise e - logger.info("API created") - return api +#!/usr/bin/env python3 +import tweepy +import logging +import os + +logger = logging.getLogger() + + +def create_api(): + consumer_key = os.getenv("CONSUMER_KEY") + consumer_secret = os.getenv("CONSUMER_SECRET") + access_token = os.getenv("ACCESS_TOKEN") + access_token_secret = os.getenv("ACCESS_TOKEN_SECRET") + + auth = tweepy.OAuthHandler(consumer_key, consumer_secret) + auth.set_access_token(access_token, access_token_secret) + api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True) + try: + api.verify_credentials() + except Exception as e: + logger.error("Error creating API", exc_info=True) + raise e + logger.info("API created") + return api diff --git a/tweet_bot/favretweet.py b/tweet_bot/favretweet.py index cf3d82d56..ca093ea33 100644 --- a/tweet_bot/favretweet.py +++ b/tweet_bot/favretweet.py @@ -1,69 +1,69 @@ -#!/usr/bin/env python3 - -import tweepy -import logging -from config import create_api - - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger() - -""" -Resuable api object from config.py. -Tweepy to uses sub-classes of tweepy objects within FavRetweetListener class. -Tweepy stream to actively watch for tweets that contain certain keywords. -For each tweet, if you’re not the tweet author, it will mark the tweet as Liked and then retweet it. -""" - - -class FavRetweetListener(tweepy.StreamListener): - def __init__(self, api): - self.api = api - self.me = api.me() - - # If the tweet is a reply or not from me it will ignore it. - def on_status(self, tweet): - logger.info(f"Processing tweet id {tweet.id}") - if tweet.in_reply_to_status_id is not None or tweet.user.id == self.me.id: - return - """ - This is like a maker, this is coming from tweepy favorited class. - If it did not favorited(Smiliary like) the tweet yet, it will favorited it if not it returns an error. - Try/Except is necessary to handling possible Errors. - """ - if not tweet.favorited: - try: - tweet.favorite() - except Exception: - logger.error("Error on fav", exc_info=True) - """ - A similar case like favorited class. - If it did not retweeted the tweet yet, it will retweeted it if not it returns an error. - Try/Except is necessary to handling possible Errors. - """ - if not tweet.retweeted: - try: - tweet.retweet() - except Exception: - logger.error("Error on fav and retweet", exc_info=True) - - # Logger for errors. - def on_error(self, status): - logger.error(status) - - -""" -The main uses a stream to filter tweets that contain the words of a list as keywords parametrs. -Bellow we used ["Python", "Tweepy", "Hacktoberfest"] -""" - - -def main(keywords): - api = create_api() - tweets_listener = FavRetweetListener(api) - stream = tweepy.Stream(api.auth, tweets_listener) - stream.filter(track=keywords, languages=["en"]) - - -if __name__ == "__main__": - main(["Python", "Tweepy", "Hacktoberfest"]) +#!/usr/bin/env python3 + +import tweepy +import logging +from config import create_api + + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger() + +""" +Resuable api object from config.py. +Tweepy to uses sub-classes of tweepy objects within FavRetweetListener class. +Tweepy stream to actively watch for tweets that contain certain keywords. +For each tweet, if you’re not the tweet author, it will mark the tweet as Liked and then retweet it. +""" + + +class FavRetweetListener(tweepy.StreamListener): + def __init__(self, api): + self.api = api + self.me = api.me() + + # If the tweet is a reply or not from me it will ignore it. + def on_status(self, tweet): + logger.info(f"Processing tweet id {tweet.id}") + if tweet.in_reply_to_status_id is not None or tweet.user.id == self.me.id: + return + """ + This is like a maker, this is coming from tweepy favorited class. + If it did not favorited(Smiliary like) the tweet yet, it will favorited it if not it returns an error. + Try/Except is necessary to handling possible Errors. + """ + if not tweet.favorited: + try: + tweet.favorite() + except Exception: + logger.error("Error on fav", exc_info=True) + """ + A similar case like favorited class. + If it did not retweeted the tweet yet, it will retweeted it if not it returns an error. + Try/Except is necessary to handling possible Errors. + """ + if not tweet.retweeted: + try: + tweet.retweet() + except Exception: + logger.error("Error on fav and retweet", exc_info=True) + + # Logger for errors. + def on_error(self, status): + logger.error(status) + + +""" +The main uses a stream to filter tweets that contain the words of a list as keywords parametrs. +Bellow we used ["Python", "Tweepy", "Hacktoberfest"] +""" + + +def main(keywords): + api = create_api() + tweets_listener = FavRetweetListener(api) + stream = tweepy.Stream(api.auth, tweets_listener) + stream.filter(track=keywords, languages=["en"]) + + +if __name__ == "__main__": + main(["Python", "Tweepy", "Hacktoberfest"]) diff --git a/tweet_bot/followfollowers.py b/tweet_bot/followfollowers.py index 5ac591bbc..98c813cd4 100644 --- a/tweet_bot/followfollowers.py +++ b/tweet_bot/followfollowers.py @@ -1,41 +1,41 @@ -#!/usr/bin/env python3 - -import tweepy -import logging -from config import create_api -import time - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger() - -''' -A lot of Twitter API endpoints use pagination to return their results. -Tweepy cursors take away part of the complexity of working with paginated results. -The Cursor object is iterable and takes care of fetching the various result pages transparently. -''' - - -def follow_followers(api): - logger.info("Retrieving and following followers") - for follower in tweepy.Cursor(api.followers).items(): - if not follower.following: - logger.info(f"Following {follower.name}") - follower.follow() - - -""" -The Bot gets list of followers every minutes (adjustable within time.sleep param) -and iterate through it to follow user who are not already followed. -""" - - -def main(): - api = create_api() - while True: - follow_followers(api) - logger.info("Waiting...") - time.sleep(60) - - -if __name__ == "__main__": - main() +#!/usr/bin/env python3 + +import tweepy +import logging +from config import create_api +import time + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger() + +''' +A lot of Twitter API endpoints use pagination to return their results. +Tweepy cursors take away part of the complexity of working with paginated results. +The Cursor object is iterable and takes care of fetching the various result pages transparently. +''' + + +def follow_followers(api): + logger.info("Retrieving and following followers") + for follower in tweepy.Cursor(api.followers).items(): + if not follower.following: + logger.info(f"Following {follower.name}") + follower.follow() + + +""" +The Bot gets list of followers every minutes (adjustable within time.sleep param) +and iterate through it to follow user who are not already followed. +""" + + +def main(): + api = create_api() + while True: + follow_followers(api) + logger.info("Waiting...") + time.sleep(60) + + +if __name__ == "__main__": + main() diff --git a/tweet_bot/makefile b/tweet_bot/makefile index e78e53c81..7aafa604a 100644 --- a/tweet_bot/makefile +++ b/tweet_bot/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/tweet_bot/requirements.txt b/tweet_bot/requirements.txt index 36702fccf..5eb95f566 100644 --- a/tweet_bot/requirements.txt +++ b/tweet_bot/requirements.txt @@ -1,10 +1,10 @@ -certifi==2020.6.20 -chardet==3.0.4 -idna==2.10 -oauthlib==3.1.0 -PySocks==1.7.1 -requests==2.24.0 -requests-oauthlib==1.3.0 -six==1.15.0 -tweepy==3.9.0 -urllib3==1.25.10 +certifi==2020.6.20 +chardet==3.0.4 +idna==2.10 +oauthlib==3.1.0 +PySocks==1.7.1 +requests==2.24.0 +requests-oauthlib==1.3.0 +six==1.15.0 +tweepy==3.9.0 +urllib3==1.25.10 diff --git a/tweet_bot/tweet-cli.py b/tweet_bot/tweet-cli.py index bcf79e1cb..391196427 100644 --- a/tweet_bot/tweet-cli.py +++ b/tweet_bot/tweet-cli.py @@ -1,22 +1,22 @@ -#!/usr/bin/env python3 -from sys import argv -from config import create_api - -usage = """ -usage: - tweet-cli "Tweet Text" -example: - tweet-cli "this is my tweet from tweet-cli" -""" - - -def tweet_cli(api): - if not len(argv) == 2: - print(usage) - else: - api.update_status(argv[1]) - - -if __name__ == "__main__": - api = create_api() - tweet_cli(api) +#!/usr/bin/env python3 +from sys import argv +from config import create_api + +usage = """ +usage: + tweet-cli "Tweet Text" +example: + tweet-cli "this is my tweet from tweet-cli" +""" + + +def tweet_cli(api): + if not len(argv) == 2: + print(usage) + else: + api.update_status(argv[1]) + + +if __name__ == "__main__": + api = create_api() + tweet_cli(api) diff --git a/url_shortener/README.md b/url_shortener/README.md index afc542cfe..6326b263c 100644 --- a/url_shortener/README.md +++ b/url_shortener/README.md @@ -1,26 +1,26 @@ -#URL's Shortner -A simple script in python which is used to shorten the url of the given url and it can be use for make short url's of multiple urls at the same time. - -## Modules Used - -- pyshorteners -- sys - -## Requirements - -- Run the following in the directory containing the script files. - -```bash -pip install pyshorteners -``` - -- Then run the below command - -```bash -python url.py "https://www.google.com/" "https://beebom.com" -``` - -- OR -```bash -python url.py "https://www.google.com/" +#URL's Shortner +A simple script in python which is used to shorten the url of the given url and it can be use for make short url's of multiple urls at the same time. + +## Modules Used + +- pyshorteners +- sys + +## Requirements + +- Run the following in the directory containing the script files. + +```bash +pip install pyshorteners +``` + +- Then run the below command + +```bash +python url.py "https://www.google.com/" "https://beebom.com" +``` + +- OR +```bash +python url.py "https://www.google.com/" ``` \ No newline at end of file diff --git a/url_shortener/makefile b/url_shortener/makefile index e78e53c81..7aafa604a 100644 --- a/url_shortener/makefile +++ b/url_shortener/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/url_shortener/url.py b/url_shortener/url.py index b6b70b9ed..deaba1ff6 100644 --- a/url_shortener/url.py +++ b/url_shortener/url.py @@ -1,20 +1,20 @@ -# Title :- URL Shortener -# The URL shortener is application which takes url input from user and shorts it -import pyshorteners -import sys - - -# url converter function -def make_short(url): - shorturl = pyshorteners.Shortener().tinyurl.short(url) - return shorturl - - -# this will take multiple url as input -def main(): - for cooked_url in map(make_short, sys.argv[1:]): - print(cooked_url) - - -if __name__ == '__main__': - main() +# Title :- URL Shortener +# The URL shortener is application which takes url input from user and shorts it +import pyshorteners +import sys + + +# url converter function +def make_short(url): + shorturl = pyshorteners.Shortener().tinyurl.short(url) + return shorturl + + +# this will take multiple url as input +def main(): + for cooked_url in map(make_short, sys.argv[1:]): + print(cooked_url) + + +if __name__ == '__main__': + main() diff --git a/video_cropper/README.md b/video_cropper/README.md index 1d5a198dc..c566022e8 100644 --- a/video_cropper/README.md +++ b/video_cropper/README.md @@ -1,63 +1,63 @@ -# video_cropper -Simple command line utility to crop videos -## Installing the Dependencies -This program requires `ffmpeg` and `ffmpeg-python` to run. -It also requires that `ffmpeg` be added to your PATH - -For `ffmpeg-python` run: -``` -pip3 install ffmpeg-python -``` -For `ffmpeg` you can usually download it on any Linux distro through your package manager. -On Windows you can download builds from [the FFMPEG official downloads page](https://ffmpeg.org/download.html) and then add `ffmpeg` to your PATH. -[This tutorial](https://www.thewindowsclub.com/how-to-install-ffmpeg-on-windows-10) tells you how. - -## Usage -``` -$ python video_cropper.py --help -usage: video_cropper.py [-h] [-i INPUT] [-c CROP] [-t TOP] [-b BOTTOM] [-l LEFT] [-r RIGHT] [-o OUTPUT] [-y] - -optional arguments: - -h, --help show this help message and exit - -i INPUT, --input INPUT - the file to crop - -c CROP, --crop CROP the amount to crop (pixels or percent) in the format "TOP,BOTTOM,LEFT,RIGHT" - -t TOP, --top TOP the amount to crop (pixels or percent) off the top of the video - -b BOTTOM, --bottom BOTTOM - the amount to crop (pixels or percent) off the bottom of the video - -l LEFT, --left LEFT the amount to crop (pixels or percent) off the left of the video - -r RIGHT, --right RIGHT - the amount to crop (pixels or percent) off the right of the video - -o OUTPUT, --output OUTPUT - the file to output to (cannot be the same as input file) - -y, --yes skip the prompt to confirm overwriting a file -``` - -Crop 50 pixels off of each side of the video -``` -python video_cropper.py -i example.mp4 -c 50,50,50,50 -o example_cropped.mp4 -``` -Crop 10% off of each side of the video -``` -python video_cropper.py -i example.mp4 -c 10%,10%,10%,10% -o example_cropped.mp4 -``` -Crop 10 pixels off of the top and bottom -``` -python video_cropper.py -i example.mp4 -t 10 -b 10 -o example_cropped.mp4 -``` -Crop 15 pixels off of the left and right -``` -python video_cropper.py -i example.mp4 -l 15 -r 15 -o example_cropped.mp4 -``` -Crop 30 pixels off the top and 12 pixels off the right -``` -python video_cropper.py -i example.mp4 -t 30 -r 12 -o example_cropped.mp4 -``` -Crop 10% off the top -``` -python video_cropper.py -i example.mp4 -t 10% -o example_cropped.mp4 -``` -Crop 10% off the left and 20 pixels off the right -``` -python video_cropper.py -i example.mp4 -l 10% -r 20 -o example_cropped.mp4 +# video_cropper +Simple command line utility to crop videos +## Installing the Dependencies +This program requires `ffmpeg` and `ffmpeg-python` to run. +It also requires that `ffmpeg` be added to your PATH + +For `ffmpeg-python` run: +``` +pip3 install ffmpeg-python +``` +For `ffmpeg` you can usually download it on any Linux distro through your package manager. +On Windows you can download builds from [the FFMPEG official downloads page](https://ffmpeg.org/download.html) and then add `ffmpeg` to your PATH. +[This tutorial](https://www.thewindowsclub.com/how-to-install-ffmpeg-on-windows-10) tells you how. + +## Usage +``` +$ python video_cropper.py --help +usage: video_cropper.py [-h] [-i INPUT] [-c CROP] [-t TOP] [-b BOTTOM] [-l LEFT] [-r RIGHT] [-o OUTPUT] [-y] + +optional arguments: + -h, --help show this help message and exit + -i INPUT, --input INPUT + the file to crop + -c CROP, --crop CROP the amount to crop (pixels or percent) in the format "TOP,BOTTOM,LEFT,RIGHT" + -t TOP, --top TOP the amount to crop (pixels or percent) off the top of the video + -b BOTTOM, --bottom BOTTOM + the amount to crop (pixels or percent) off the bottom of the video + -l LEFT, --left LEFT the amount to crop (pixels or percent) off the left of the video + -r RIGHT, --right RIGHT + the amount to crop (pixels or percent) off the right of the video + -o OUTPUT, --output OUTPUT + the file to output to (cannot be the same as input file) + -y, --yes skip the prompt to confirm overwriting a file +``` + +Crop 50 pixels off of each side of the video +``` +python video_cropper.py -i example.mp4 -c 50,50,50,50 -o example_cropped.mp4 +``` +Crop 10% off of each side of the video +``` +python video_cropper.py -i example.mp4 -c 10%,10%,10%,10% -o example_cropped.mp4 +``` +Crop 10 pixels off of the top and bottom +``` +python video_cropper.py -i example.mp4 -t 10 -b 10 -o example_cropped.mp4 +``` +Crop 15 pixels off of the left and right +``` +python video_cropper.py -i example.mp4 -l 15 -r 15 -o example_cropped.mp4 +``` +Crop 30 pixels off the top and 12 pixels off the right +``` +python video_cropper.py -i example.mp4 -t 30 -r 12 -o example_cropped.mp4 +``` +Crop 10% off the top +``` +python video_cropper.py -i example.mp4 -t 10% -o example_cropped.mp4 +``` +Crop 10% off the left and 20 pixels off the right +``` +python video_cropper.py -i example.mp4 -l 10% -r 20 -o example_cropped.mp4 ``` \ No newline at end of file diff --git a/video_cropper/video_cropper.py b/video_cropper/video_cropper.py index 462bc1c11..12357681a 100644 --- a/video_cropper/video_cropper.py +++ b/video_cropper/video_cropper.py @@ -1,120 +1,120 @@ -import ffmpeg -import argparse -import sys -import os - - -def to_int(a, rel_to): - ''' - Converts string to integer. - - If string contains "%" it converts it to a float and multiplies by rel_to - EG: 50% -> 0.5*rel_to - ''' - if type(a) == int: - return a - else: - if '%' in a: - return int((int(a.replace('%', '')) / 100) * rel_to) - else: - return int(a) - - -if __name__ == '__main__': - # set up the arguments to be parsed - parser = argparse.ArgumentParser() - - parser.add_argument('-i', '--input', type=str, help='the file to crop') - parser.add_argument('-c', '--crop', type=str, help='the amount to crop in the format "TOP,BOTTOM,LEFT,RIGHT"') - parser.add_argument('-t', '--top', type=str, help='the amount to crop off the top of the video') - parser.add_argument('-b', '--bottom', type=str, help='the amount to crop off the bottom of the video') - parser.add_argument('-l', '--left', type=str, help='the amount to crop off the left of the video') - parser.add_argument('-r', '--right', type=str, help='the amount to crop off the right of the video') - parser.add_argument('-o', '--output', type=str, help='the file to output to (cannot be the same as input file)') - parser.add_argument('-y', '--yes', action='store_true', help='skip the prompt to confirm overwriting a file') - - args = parser.parse_args() - - # check whether the user is using the --crop arg - # or a combination of the --left, --right, --top, --bottom args - if args.crop is not None: - args.crop = args.crop.split(',') - if len(args.crop) == 4: - # check it is the right length - crop = { - 'top': args.crop[0], - 'bottom': args.crop[1], - 'left': args.crop[2], - 'right': args.crop[3] - } - else: - # if the length is not 4 then the format is not supported - sys.stderr.write( - 'ERROR: crop arg must be in the format "TOP,BOTTOM,LEFT,RIGHT"' - ) - sys.exit(1) - else: - # parse all of the other possible crop kwargs - crop = {'top': 0, 'bottom': 0, 'left': 0, 'right': 0} - if args.top: - crop['top'] = args.top - if args.bottom: - crop['bottom'] = args.bottom - if args.left: - crop['left'] = args.left - if args.right: - crop['right'] = args.right - # if no values were supplied all crops will equal 0 - if all(i == 0 for i in crop.values()): - sys.stderr.write('ERROR: no crop applied. All crops equal to 0') - sys.exit(1) - - # validate that args.input is a file - if args.input is None or not os.path.isfile(args.input): - sys.stderr.write('ERROR: input file does not exist') - sys.exit(1) - - # find the video data for the input file - # and find it's default video stream (the first one) - metadata = ffmpeg.probe(args.input) - vid_stream = None - for stream in metadata['streams']: - if stream['codec_type'] == 'video': - vid_stream = stream - break - - # if no video stream has been found we cannot crop it - if vid_stream is None: - sys.stderr.write('ERROR: could not find valid video stream in file') - sys.exit(1) - - # convert all crop values to an integer - crop['top'] = to_int(crop['top'], vid_stream['height']) - crop['bottom'] = to_int(crop['bottom'], vid_stream['height']) - crop['left'] = to_int(crop['left'], vid_stream['width']) - crop['right'] = to_int(crop['right'], vid_stream['width']) - - # calculate the new width and height of the video - width = vid_stream['width'] - (crop['left'] + crop['right']) - height = vid_stream['height'] - (crop['top'] + crop['bottom']) - if width <= 0: - # the new width cannot be less than or equal to 0 - sys.stderr.write('ERROR: resulting width must be greater than 0') - sys.exit(1) - if height <= 0: - # the new height cannot be less than or equal to 0 - sys.stderr.write('ERROR: resulting height must be greater than 0') - sys.exit(1) - - # call ffmpeg with the required args - cmd = 'ffmpeg -hide_banner -loglevel error -i "{}" -c:a copy -filter:v "crop={}:{}:{}:{}" {}{}' - cmd = cmd.format( - args.input, - width, - height, - crop['left'], - crop['top'], - "-y " if args.yes else "", - args.output - ) - os.system(cmd) +import ffmpeg +import argparse +import sys +import os + + +def to_int(a, rel_to): + ''' + Converts string to integer. + + If string contains "%" it converts it to a float and multiplies by rel_to + EG: 50% -> 0.5*rel_to + ''' + if type(a) == int: + return a + else: + if '%' in a: + return int((int(a.replace('%', '')) / 100) * rel_to) + else: + return int(a) + + +if __name__ == '__main__': + # set up the arguments to be parsed + parser = argparse.ArgumentParser() + + parser.add_argument('-i', '--input', type=str, help='the file to crop') + parser.add_argument('-c', '--crop', type=str, help='the amount to crop in the format "TOP,BOTTOM,LEFT,RIGHT"') + parser.add_argument('-t', '--top', type=str, help='the amount to crop off the top of the video') + parser.add_argument('-b', '--bottom', type=str, help='the amount to crop off the bottom of the video') + parser.add_argument('-l', '--left', type=str, help='the amount to crop off the left of the video') + parser.add_argument('-r', '--right', type=str, help='the amount to crop off the right of the video') + parser.add_argument('-o', '--output', type=str, help='the file to output to (cannot be the same as input file)') + parser.add_argument('-y', '--yes', action='store_true', help='skip the prompt to confirm overwriting a file') + + args = parser.parse_args() + + # check whether the user is using the --crop arg + # or a combination of the --left, --right, --top, --bottom args + if args.crop is not None: + args.crop = args.crop.split(',') + if len(args.crop) == 4: + # check it is the right length + crop = { + 'top': args.crop[0], + 'bottom': args.crop[1], + 'left': args.crop[2], + 'right': args.crop[3] + } + else: + # if the length is not 4 then the format is not supported + sys.stderr.write( + 'ERROR: crop arg must be in the format "TOP,BOTTOM,LEFT,RIGHT"' + ) + sys.exit(1) + else: + # parse all of the other possible crop kwargs + crop = {'top': 0, 'bottom': 0, 'left': 0, 'right': 0} + if args.top: + crop['top'] = args.top + if args.bottom: + crop['bottom'] = args.bottom + if args.left: + crop['left'] = args.left + if args.right: + crop['right'] = args.right + # if no values were supplied all crops will equal 0 + if all(i == 0 for i in crop.values()): + sys.stderr.write('ERROR: no crop applied. All crops equal to 0') + sys.exit(1) + + # validate that args.input is a file + if args.input is None or not os.path.isfile(args.input): + sys.stderr.write('ERROR: input file does not exist') + sys.exit(1) + + # find the video data for the input file + # and find it's default video stream (the first one) + metadata = ffmpeg.probe(args.input) + vid_stream = None + for stream in metadata['streams']: + if stream['codec_type'] == 'video': + vid_stream = stream + break + + # if no video stream has been found we cannot crop it + if vid_stream is None: + sys.stderr.write('ERROR: could not find valid video stream in file') + sys.exit(1) + + # convert all crop values to an integer + crop['top'] = to_int(crop['top'], vid_stream['height']) + crop['bottom'] = to_int(crop['bottom'], vid_stream['height']) + crop['left'] = to_int(crop['left'], vid_stream['width']) + crop['right'] = to_int(crop['right'], vid_stream['width']) + + # calculate the new width and height of the video + width = vid_stream['width'] - (crop['left'] + crop['right']) + height = vid_stream['height'] - (crop['top'] + crop['bottom']) + if width <= 0: + # the new width cannot be less than or equal to 0 + sys.stderr.write('ERROR: resulting width must be greater than 0') + sys.exit(1) + if height <= 0: + # the new height cannot be less than or equal to 0 + sys.stderr.write('ERROR: resulting height must be greater than 0') + sys.exit(1) + + # call ffmpeg with the required args + cmd = 'ffmpeg -hide_banner -loglevel error -i "{}" -c:a copy -filter:v "crop={}:{}:{}:{}" {}{}' + cmd = cmd.format( + args.input, + width, + height, + crop['left'], + crop['top'], + "-y " if args.yes else "", + args.output + ) + os.system(cmd) diff --git a/video_desaturator/README.md b/video_desaturator/README.md index c94c19371..1c0a8b6d3 100644 --- a/video_desaturator/README.md +++ b/video_desaturator/README.md @@ -1,42 +1,42 @@ -# video_desaturator -Simple command line utility to alter the saturation level of videos -## Installing the Dependencies -This program requires `ffmpeg` to run. -It also requires that `ffmpeg` be added to your PATH - -You can usually download it on any Linux distro through your package manager. -On Windows you can download builds from [the FFMPEG official downloads page](https://ffmpeg.org/download.html) and then add `ffmpeg` to your PATH. -[This tutorial](https://www.thewindowsclub.com/how-to-install-ffmpeg-on-windows-10) tells you how. - -## Usage -``` -$ python video_desaturator.py --help -usage: video_desaturator.py [-h] [-l LEVEL] [-y] in_file out_file - -positional arguments: - in_file the file to desaturate - out_file the file to output to - -optional arguments: - -h, --help show this help message and exit - -l LEVEL, --level LEVEL - the saturation percentage to use (default: 0, max: 300) - -y, --yes skip the prompt to overwrite the file -``` - -Set a video's saturation level to 0% (black and white) -``` -python video_desaturator.py example.mp4 example-out.mp4 -``` -Set a video's saturation level to 50% -``` -python video_desaturator.py example.mp4 -l 50 example-out.mp4 -``` -Set a video's saturation level to 100% (no change) -``` -python video_desaturator.py example.mp4 -l 100 example-out.mp4 -``` -Set a video's saturation level to 300% -``` -python video_desaturator.py example.mp4 -l 300 example-out.mp4 +# video_desaturator +Simple command line utility to alter the saturation level of videos +## Installing the Dependencies +This program requires `ffmpeg` to run. +It also requires that `ffmpeg` be added to your PATH + +You can usually download it on any Linux distro through your package manager. +On Windows you can download builds from [the FFMPEG official downloads page](https://ffmpeg.org/download.html) and then add `ffmpeg` to your PATH. +[This tutorial](https://www.thewindowsclub.com/how-to-install-ffmpeg-on-windows-10) tells you how. + +## Usage +``` +$ python video_desaturator.py --help +usage: video_desaturator.py [-h] [-l LEVEL] [-y] in_file out_file + +positional arguments: + in_file the file to desaturate + out_file the file to output to + +optional arguments: + -h, --help show this help message and exit + -l LEVEL, --level LEVEL + the saturation percentage to use (default: 0, max: 300) + -y, --yes skip the prompt to overwrite the file +``` + +Set a video's saturation level to 0% (black and white) +``` +python video_desaturator.py example.mp4 example-out.mp4 +``` +Set a video's saturation level to 50% +``` +python video_desaturator.py example.mp4 -l 50 example-out.mp4 +``` +Set a video's saturation level to 100% (no change) +``` +python video_desaturator.py example.mp4 -l 100 example-out.mp4 +``` +Set a video's saturation level to 300% +``` +python video_desaturator.py example.mp4 -l 300 example-out.mp4 ``` \ No newline at end of file diff --git a/video_desaturator/video_desaturator.py b/video_desaturator/video_desaturator.py index 0e5970088..e20ab441b 100644 --- a/video_desaturator/video_desaturator.py +++ b/video_desaturator/video_desaturator.py @@ -1,42 +1,42 @@ -import argparse -import sys -import os - - -if __name__ == '__main__': - # set up the arguments to be parsed - parser = argparse.ArgumentParser() - - parser.add_argument('-l', '--level', type=int, help='the saturation percentage to use (default: 0, max: 300)') - parser.add_argument('-y', '--yes', action='store_true', help='skip the prompt to overwrite the file') - parser.add_argument('in_file', type=str, help='the file to desaturate') - parser.add_argument('out_file', type=str, help='the file to output to') - - args = parser.parse_args() - - # check if the supplied file exists - if not os.path.isfile(args.in_file): - sys.stderr.write('ERROR: input file does not exist') - sys.exit(1) - - # check that the level given is within range - level = 0 - if args.level is not None: - if args.level < 0 or args.level > 300: - sys.stderr.write('ERROR: saturation level must be between 0 and 300') - sys.exit(1) - level = args.level - - # ffmpeg allows saturation values between 0.0 and 3.0 - # so we convert the percentage value here - level = level / 100 - - # create the ffmpeg command and run it - cmd = 'ffmpeg -hide_banner -loglevel error -i "{}" -c:a copy -vf "eq=saturation={}" {}{}' - cmd = cmd.format( - args.in_file, - level, - "-y " if args.yes else "", - args.out_file - ) - os.system(cmd) +import argparse +import sys +import os + + +if __name__ == '__main__': + # set up the arguments to be parsed + parser = argparse.ArgumentParser() + + parser.add_argument('-l', '--level', type=int, help='the saturation percentage to use (default: 0, max: 300)') + parser.add_argument('-y', '--yes', action='store_true', help='skip the prompt to overwrite the file') + parser.add_argument('in_file', type=str, help='the file to desaturate') + parser.add_argument('out_file', type=str, help='the file to output to') + + args = parser.parse_args() + + # check if the supplied file exists + if not os.path.isfile(args.in_file): + sys.stderr.write('ERROR: input file does not exist') + sys.exit(1) + + # check that the level given is within range + level = 0 + if args.level is not None: + if args.level < 0 or args.level > 300: + sys.stderr.write('ERROR: saturation level must be between 0 and 300') + sys.exit(1) + level = args.level + + # ffmpeg allows saturation values between 0.0 and 3.0 + # so we convert the percentage value here + level = level / 100 + + # create the ffmpeg command and run it + cmd = 'ffmpeg -hide_banner -loglevel error -i "{}" -c:a copy -vf "eq=saturation={}" {}{}' + cmd = cmd.format( + args.in_file, + level, + "-y " if args.yes else "", + args.out_file + ) + os.system(cmd) diff --git a/video_merger/README.md b/video_merger/README.md index 3a9a1ba41..b79e19089 100644 --- a/video_merger/README.md +++ b/video_merger/README.md @@ -1,8 +1,8 @@ -# ffmpeg-python video merger - -Program requires a minimum of 3 arguments, two video files to merge, and the output file in this format: -``` -python video_merger.py {input 1} {input 2} {output} -``` - -Any amount of input files could be added, but the output file must be the last argument. +# ffmpeg-python video merger + +Program requires a minimum of 3 arguments, two video files to merge, and the output file in this format: +``` +python video_merger.py {input 1} {input 2} {output} +``` + +Any amount of input files could be added, but the output file must be the last argument. diff --git a/video_merger/requirements.txt b/video_merger/requirements.txt index 333541919..a1942593a 100644 --- a/video_merger/requirements.txt +++ b/video_merger/requirements.txt @@ -1 +1 @@ -ffmpeg-python +ffmpeg-python diff --git a/video_merger/video_merger.py b/video_merger/video_merger.py index fea6aff84..3cdd9f1ca 100644 --- a/video_merger/video_merger.py +++ b/video_merger/video_merger.py @@ -1,13 +1,13 @@ -import sys -import ffmpeg - - -if __name__ == '__main__': - print(sys.argv) - print(len(sys.argv)) - print(str(sys.argv[len(sys.argv) - 1])) - list = open("list.txt", "w") - for i in range(1, len(sys.argv) - 1): - list.write("file {}\n".format(sys.argv[i])) - list.close() - ffmpeg.input("list.txt", format='concat', safe=0).output(sys.argv[len(sys.argv) - 1], c='copy').run() +import sys +import ffmpeg + + +if __name__ == '__main__': + print(sys.argv) + print(len(sys.argv)) + print(str(sys.argv[len(sys.argv) - 1])) + list = open("list.txt", "w") + for i in range(1, len(sys.argv) - 1): + list.write("file {}\n".format(sys.argv[i])) + list.close() + ffmpeg.input("list.txt", format='concat', safe=0).output(sys.argv[len(sys.argv) - 1], c='copy').run() diff --git a/video_player/README.md b/video_player/README.md index 6ff365203..9ec8f3631 100644 --- a/video_player/README.md +++ b/video_player/README.md @@ -1,10 +1,10 @@ -# OpenCV video player - -Program takes one argument, your video's filename. -to use, run -``` -python video_player.py 'filename' -``` - -while watching the video, press "q" to exit, and Space to pause the video. - +# OpenCV video player + +Program takes one argument, your video's filename. +to use, run +``` +python video_player.py 'filename' +``` + +while watching the video, press "q" to exit, and Space to pause the video. + diff --git a/video_player/requirements.txt b/video_player/requirements.txt index 6f372d8a1..74be205b7 100644 --- a/video_player/requirements.txt +++ b/video_player/requirements.txt @@ -1 +1 @@ -cv2 +cv2 diff --git a/video_player/videoplayer.py b/video_player/videoplayer.py index b35d17b8b..a939e2b57 100644 --- a/video_player/videoplayer.py +++ b/video_player/videoplayer.py @@ -1,37 +1,37 @@ -import cv2 -import sys - - -def play_video(cap): - is_paused = False - while (cap.isOpened()): - if not is_paused: - ret, frame = cap.read() - if ret: - cv2.imshow('Frame', frame) - key = cv2.waitKey(25) - if key == 113: - break - elif key == 32: - is_paused = not is_paused - else: - break - return cap - - -def cleanup(cap): - cap.release() - cv2.destroyAllWindows() - - -def cap_check(path): - print("Creating capture device at path {}".format(path)) - cap = cv2.VideoCapture(path) - if not cap.isOpened(): - print("Error opening video stream or file") - else: - return cap - - -if __name__ == '__main__': - cleanup(play_video(cap_check(sys.argv[1]))) +import cv2 +import sys + + +def play_video(cap): + is_paused = False + while (cap.isOpened()): + if not is_paused: + ret, frame = cap.read() + if ret: + cv2.imshow('Frame', frame) + key = cv2.waitKey(25) + if key == 113: + break + elif key == 32: + is_paused = not is_paused + else: + break + return cap + + +def cleanup(cap): + cap.release() + cv2.destroyAllWindows() + + +def cap_check(path): + print("Creating capture device at path {}".format(path)) + cap = cv2.VideoCapture(path) + if not cap.isOpened(): + print("Error opening video stream or file") + else: + return cap + + +if __name__ == '__main__': + cleanup(play_video(cap_check(sys.argv[1]))) diff --git a/video_textadder/README.md b/video_textadder/README.md index 69cc8b8c4..acbfe8f06 100644 --- a/video_textadder/README.md +++ b/video_textadder/README.md @@ -1,46 +1,46 @@ -# Video Textadder - -Add a watermark on top-center of the video. - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -### Pre-requisites -Setup virtual environment from previous step or install requirements manually: - -* ImageMagick installation -``` -$ sudo apt install imagemagick -``` - -* moviepy installation -``` -$ pip install moviepy -``` - -### How to Use -``` -$ python video-textadder.py [-h] [-f F] [-t T] [-s S] [-n N] -``` - -If not adding any argument, the script will add the default watermark text on the top center of demo.mp4 and generate "demo_title.mp4" as default - -``` -optional arguments: - -h, --help show this help message and exit - -f F The file path of target video. ex. /home/user/example.mp4. - Default value is "demo.mp4" - -t T The text you want to add to video top. ex. "Hellow Video" - -s S The font size of video watermark. ex. 30 - -n N The new file name. Default value is {current file - name}_title.mp4 -``` - - - - - +# Video Textadder + +Add a watermark on top-center of the video. + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +### Pre-requisites +Setup virtual environment from previous step or install requirements manually: + +* ImageMagick installation +``` +$ sudo apt install imagemagick +``` + +* moviepy installation +``` +$ pip install moviepy +``` + +### How to Use +``` +$ python video-textadder.py [-h] [-f F] [-t T] [-s S] [-n N] +``` + +If not adding any argument, the script will add the default watermark text on the top center of demo.mp4 and generate "demo_title.mp4" as default + +``` +optional arguments: + -h, --help show this help message and exit + -f F The file path of target video. ex. /home/user/example.mp4. + Default value is "demo.mp4" + -t T The text you want to add to video top. ex. "Hellow Video" + -s S The font size of video watermark. ex. 30 + -n N The new file name. Default value is {current file + name}_title.mp4 +``` + + + + + diff --git a/video_textadder/makefile b/video_textadder/makefile index dbcb008b6..00cc941a5 100644 --- a/video_textadder/makefile +++ b/video_textadder/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/video_textadder/requirements.txt b/video_textadder/requirements.txt index a384113ea..a21d91e87 100644 --- a/video_textadder/requirements.txt +++ b/video_textadder/requirements.txt @@ -1 +1 @@ -moviepy +moviepy diff --git a/video_textadder/video-textadder.py b/video_textadder/video-textadder.py index 7675368aa..d956a54b4 100644 --- a/video_textadder/video-textadder.py +++ b/video_textadder/video-textadder.py @@ -1,81 +1,81 @@ -from moviepy.editor import CompositeVideoClip, VideoFileClip -from moviepy.video.VideoClip import TextClip -import os -import argparse - -# Define the base directory -base_dir = os.path.dirname(os.path.abspath(__file__)) - -# Define CLI arguments -parser = argparse.ArgumentParser() -parser.add_argument( - '-f', - type=str, - help='The file path of target video. ' - + 'ex. /home/user/example.mp4.\nDefault value is "demo.mp4"', - default=base_dir + '/demo.mp4' -) -parser.add_argument( - '-t', - type=str, - help='The text you want to add to video top. ' - + 'ex. "Hellow Video"', - default='This is demo example' -) -parser.add_argument( - '-s', - type=int, - help='The font size of video watermark. ' - + 'ex. 30', - default='30' -) -parser.add_argument( - '-n', - type=str, - help='The new file name.\n' - + 'Default value is {current file name}_title.mp4', -) - -# Define Variable -args = parser.parse_args() -video_path = args.f -video_watermark = args.t -font_size = args.s - -# Check whether or not the input video path is valid. If not, ask user to input again. -while True: - try: - video = VideoFileClip(video_path) - print('video resultion: ', video.size) - break - except Exception: - print( - 'Directory or file is not valid,' - + ' please enter a valid file directory ...') - video_path = str(input('Enter the video path again (absolute path without space): ')) - -origin_file = (lambda x: x.split('/')[-1])(video_path) - -if args.n: - new_file = args.n -else: - new_file = f'{origin_file.split(".")[0]}_title.{origin_file.split(".")[1]}' - - -def add_text(content, font_size): - ''' - add text on the top of video stream - ''' - txt_clip = (TextClip(content, fontsize=font_size, color='white') - .set_position('top') - .set_duration(video.duration)) - result = CompositeVideoClip([video, txt_clip]) - result.write_videofile(new_file) - - -def main(): - add_text(video_watermark, font_size) - - -if __name__ == '__main__': - main() +from moviepy.editor import CompositeVideoClip, VideoFileClip +from moviepy.video.VideoClip import TextClip +import os +import argparse + +# Define the base directory +base_dir = os.path.dirname(os.path.abspath(__file__)) + +# Define CLI arguments +parser = argparse.ArgumentParser() +parser.add_argument( + '-f', + type=str, + help='The file path of target video. ' + + 'ex. /home/user/example.mp4.\nDefault value is "demo.mp4"', + default=base_dir + '/demo.mp4' +) +parser.add_argument( + '-t', + type=str, + help='The text you want to add to video top. ' + + 'ex. "Hellow Video"', + default='This is demo example' +) +parser.add_argument( + '-s', + type=int, + help='The font size of video watermark. ' + + 'ex. 30', + default='30' +) +parser.add_argument( + '-n', + type=str, + help='The new file name.\n' + + 'Default value is {current file name}_title.mp4', +) + +# Define Variable +args = parser.parse_args() +video_path = args.f +video_watermark = args.t +font_size = args.s + +# Check whether or not the input video path is valid. If not, ask user to input again. +while True: + try: + video = VideoFileClip(video_path) + print('video resultion: ', video.size) + break + except Exception: + print( + 'Directory or file is not valid,' + + ' please enter a valid file directory ...') + video_path = str(input('Enter the video path again (absolute path without space): ')) + +origin_file = (lambda x: x.split('/')[-1])(video_path) + +if args.n: + new_file = args.n +else: + new_file = f'{origin_file.split(".")[0]}_title.{origin_file.split(".")[1]}' + + +def add_text(content, font_size): + ''' + add text on the top of video stream + ''' + txt_clip = (TextClip(content, fontsize=font_size, color='white') + .set_position('top') + .set_duration(video.duration)) + result = CompositeVideoClip([video, txt_clip]) + result.write_videofile(new_file) + + +def main(): + add_text(video_watermark, font_size) + + +if __name__ == '__main__': + main() diff --git a/video_togif/makefile b/video_togif/makefile index e78e53c81..7aafa604a 100644 --- a/video_togif/makefile +++ b/video_togif/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/voice_recorder/README.md b/voice_recorder/README.md index c3353b2d3..92a3450e8 100644 --- a/voice_recorder/README.md +++ b/voice_recorder/README.md @@ -1,23 +1,23 @@ -# VoiceRecorder - -This is a basic voice recorder with a basic GUI to start, pause, resume and stop the recording -After stopping the recording, you have to specify a file name in the command prompt - -## Prerequisites - -**Python 3.8.x** -**tkinter package** -**pyaudio package** - -Install the requirements: - -`python -m pip install -r requirements.txt --user` - -If you cannot install pyaudio with the above command checkout this site : -[Pyaudio Install Error Solution](https://stackoverflow.com/questions/52283840/i-cant-install-pyaudio-on-windows-how-to-solve-error-microsoft-visual-c-14) - -Then you can run the script! - -## Instructions to run the script - +# VoiceRecorder + +This is a basic voice recorder with a basic GUI to start, pause, resume and stop the recording +After stopping the recording, you have to specify a file name in the command prompt + +## Prerequisites + +**Python 3.8.x** +**tkinter package** +**pyaudio package** + +Install the requirements: + +`python -m pip install -r requirements.txt --user` + +If you cannot install pyaudio with the above command checkout this site : +[Pyaudio Install Error Solution](https://stackoverflow.com/questions/52283840/i-cant-install-pyaudio-on-windows-how-to-solve-error-microsoft-visual-c-14) + +Then you can run the script! + +## Instructions to run the script + `python voice_recorder.py` \ No newline at end of file diff --git a/voice_recorder/requirements.txt b/voice_recorder/requirements.txt index 644386c71..fbe14f0ea 100644 --- a/voice_recorder/requirements.txt +++ b/voice_recorder/requirements.txt @@ -1,2 +1,2 @@ -tkinter +tkinter pyaudio \ No newline at end of file diff --git a/voice_recorder/voice_recorder.py b/voice_recorder/voice_recorder.py index 1b01cb9f4..d64f5cd95 100644 --- a/voice_recorder/voice_recorder.py +++ b/voice_recorder/voice_recorder.py @@ -1,80 +1,80 @@ -import tkinter as tk -import threading -import pyaudio -import wave - - -class App(): - chunk = 1024 - sample_format = pyaudio.paInt16 - channels = 2 - fs = 44100 - state = "" - frames = [] - - def __init__(self, master): - - self.isrecording = False - self.button1 = tk.Button(main, text='rec', command=self.startrecording).grid(row=1, column=0) - self.button2 = tk.Button(main, text='pause', command=self.pause).grid(row=1, column=1) - self.button3 = tk.Button(main, text='resume', command=self.resume).grid(row=1, column=2) - self.button4 = tk.Button(main, text='stop', command=self.stoprecording).grid(row=1, column=3) - - def record(self): - - while self.isrecording: - data = self.stream.read(self.chunk) - self.frames.append(data) - - def startrecording(self): - - if(self.state == ""): - self.p = pyaudio.PyAudio() - self.stream = self.p.open(format=self.sample_format, channels=self.channels, - rate=self.fs, frames_per_buffer=self.chunk, input=True) - self.isrecording = True - self.state = "R" - print('Recording') - t = threading.Thread(target=self.record) - t.start() - - def stoprecording(self): - - if(self.state == ""): - print("Empty Recording Cannot be saved") - else: - main.destroy() - self.isrecording = False - self.state = "S" - print('recording complete') - self.filename = input('\nPlease Enter required Filename\n') - self.filename = self.filename + ".wav" - wf = wave.open(self.filename, 'wb') - wf.setnchannels(self.channels) - wf.setsampwidth(self.p.get_sample_size(self.sample_format)) - wf.setframerate(self.fs) - wf.writeframes(b''.join(self.frames)) - wf.close() - - def pause(self): - - if(self.state == "R" or self.state == "Res"): - self.isrecording = False - print("Recording Paused") - self.state = "P" - - def resume(self): - - if(self.state == "P"): - self.isrecording = True - self.state = "Res" - print("Recording Resumed") - t = threading.Thread(target=self.record) - t.start() - - -main = tk.Tk() -main.title('recorder') -main.geometry('200x50') -app = App(main) -main.mainloop() +import tkinter as tk +import threading +import pyaudio +import wave + + +class App(): + chunk = 1024 + sample_format = pyaudio.paInt16 + channels = 2 + fs = 44100 + state = "" + frames = [] + + def __init__(self, master): + + self.isrecording = False + self.button1 = tk.Button(main, text='rec', command=self.startrecording).grid(row=1, column=0) + self.button2 = tk.Button(main, text='pause', command=self.pause).grid(row=1, column=1) + self.button3 = tk.Button(main, text='resume', command=self.resume).grid(row=1, column=2) + self.button4 = tk.Button(main, text='stop', command=self.stoprecording).grid(row=1, column=3) + + def record(self): + + while self.isrecording: + data = self.stream.read(self.chunk) + self.frames.append(data) + + def startrecording(self): + + if(self.state == ""): + self.p = pyaudio.PyAudio() + self.stream = self.p.open(format=self.sample_format, channels=self.channels, + rate=self.fs, frames_per_buffer=self.chunk, input=True) + self.isrecording = True + self.state = "R" + print('Recording') + t = threading.Thread(target=self.record) + t.start() + + def stoprecording(self): + + if(self.state == ""): + print("Empty Recording Cannot be saved") + else: + main.destroy() + self.isrecording = False + self.state = "S" + print('recording complete') + self.filename = input('\nPlease Enter required Filename\n') + self.filename = self.filename + ".wav" + wf = wave.open(self.filename, 'wb') + wf.setnchannels(self.channels) + wf.setsampwidth(self.p.get_sample_size(self.sample_format)) + wf.setframerate(self.fs) + wf.writeframes(b''.join(self.frames)) + wf.close() + + def pause(self): + + if(self.state == "R" or self.state == "Res"): + self.isrecording = False + print("Recording Paused") + self.state = "P" + + def resume(self): + + if(self.state == "P"): + self.isrecording = True + self.state = "Res" + print("Recording Resumed") + t = threading.Thread(target=self.record) + t.start() + + +main = tk.Tk() +main.title('recorder') +main.geometry('200x50') +app = App(main) +main.mainloop() diff --git a/voice_to_text/README.md b/voice_to_text/README.md index 83a09f532..b3c3ef8e6 100644 --- a/voice_to_text/README.md +++ b/voice_to_text/README.md @@ -1,19 +1,19 @@ -# Voice to text -Transcribes speech from inputted audio file using PocketSphinx. -## Prerequisites -- Python 3.x -- SpeechRecognition package -# Usage Examples -- Output to terminal -``` -$ python voice_to_text.py -p whatstheweatherlike.wav -``` -- Output to file -``` -$ python voice_to_text.py -p whatstheweatherlike.wav -o text.txt -``` -- You can also use this script without the "python" for the sake of comfort on UNIX systems. -``` -$ chmod +x voice_to_text.py -$ ./voice_to_text.py -p whatstheweatherlike.wav -``` +# Voice to text +Transcribes speech from inputted audio file using PocketSphinx. +## Prerequisites +- Python 3.x +- SpeechRecognition package +# Usage Examples +- Output to terminal +``` +$ python voice_to_text.py -p whatstheweatherlike.wav +``` +- Output to file +``` +$ python voice_to_text.py -p whatstheweatherlike.wav -o text.txt +``` +- You can also use this script without the "python" for the sake of comfort on UNIX systems. +``` +$ chmod +x voice_to_text.py +$ ./voice_to_text.py -p whatstheweatherlike.wav +``` diff --git a/voice_to_text/requirements.txt b/voice_to_text/requirements.txt index dbc50236c..4929446f1 100644 --- a/voice_to_text/requirements.txt +++ b/voice_to_text/requirements.txt @@ -1 +1 @@ -SpeechRecognition +SpeechRecognition diff --git a/voice_to_text/voice_to_text.py b/voice_to_text/voice_to_text.py index f5dc315bc..26af0fdc6 100644 --- a/voice_to_text/voice_to_text.py +++ b/voice_to_text/voice_to_text.py @@ -1,36 +1,36 @@ -#!/usr/bin/env python3 - -import speech_recognition as sr -import argparse - - -parser = argparse.ArgumentParser(description=("Performs" - "voice-to-text transcription on" - "audio files using" - "PocketSphinx.")) -parser.add_argument('-p', '--path', - type=str, required=True, help="Audio file path.") -parser.add_argument('-o', '--output', type=str, - required=False, help="Optional output to a file." - "By default, the recognized" - "text is printed out." - "(Choose a file name.)") -args = parser.parse_args() - - -def main(): - if args.path: - filepath = args.path - r = sr.Recognizer() - with sr.AudioFile(filepath) as infile: - audio = r.record(infile) - if args.output: - output = args.output - with open(output, 'w') as outfile: - print(r.recognize_sphinx(audio), file=outfile) - else: - print(r.recognize_sphinx(audio)) - - -if __name__ == '__main__': - main() +#!/usr/bin/env python3 + +import speech_recognition as sr +import argparse + + +parser = argparse.ArgumentParser(description=("Performs" + "voice-to-text transcription on" + "audio files using" + "PocketSphinx.")) +parser.add_argument('-p', '--path', + type=str, required=True, help="Audio file path.") +parser.add_argument('-o', '--output', type=str, + required=False, help="Optional output to a file." + "By default, the recognized" + "text is printed out." + "(Choose a file name.)") +args = parser.parse_args() + + +def main(): + if args.path: + filepath = args.path + r = sr.Recognizer() + with sr.AudioFile(filepath) as infile: + audio = r.record(infile) + if args.output: + output = args.output + with open(output, 'w') as outfile: + print(r.recognize_sphinx(audio), file=outfile) + else: + print(r.recognize_sphinx(audio)) + + +if __name__ == '__main__': + main() diff --git a/watermark-maker/README.md b/watermark-maker/README.md index 936d069ba..da6236c61 100644 --- a/watermark-maker/README.md +++ b/watermark-maker/README.md @@ -1,15 +1,15 @@ -# PDF Watermaker - -### Getting started: -- To begin with you will have to download the required modules. You can do this by doing: - `pip install -r requirements.txt` or `pip3 install -r requirements.txt` -- After that make sure to keep the pdf you want to add the watermark to, is in the same directory as the python script. -- After executing the program it will ask you for: - -- The Text you want to use as a watermark - -- The name of the pdf file you want to add the watermark to -- The script will save the final file by the name finalDraft.pdf - -- Example result : - -![Img](./images/img1.png =250x) ![Img](./images/img2.png =250x) - +# PDF Watermaker + +### Getting started: +- To begin with you will have to download the required modules. You can do this by doing: + `pip install -r requirements.txt` or `pip3 install -r requirements.txt` +- After that make sure to keep the pdf you want to add the watermark to, is in the same directory as the python script. +- After executing the program it will ask you for: + -- The Text you want to use as a watermark + -- The name of the pdf file you want to add the watermark to +- The script will save the final file by the name finalDraft.pdf + +- Example result : + +![Img](./images/img1.png =250x) ![Img](./images/img2.png =250x) + diff --git a/watermark-maker/main.py b/watermark-maker/main.py index d6d9b0a28..71df27927 100644 --- a/watermark-maker/main.py +++ b/watermark-maker/main.py @@ -1,44 +1,44 @@ -from reportlab.pdfgen import canvas -from reportlab.lib.units import inch -from reportlab.lib import colors -from reportlab.lib.pagesizes import A4 -from PyPDF2 import PdfFileReader, PdfFileWriter - - -print("Enter file names with its extenstion!") - - -def makeWatermark(): - text = input("Enter the watermark text here:") - pdf6 = canvas.Canvas("watermark.pdf", pagesize=A4) - pdf6.translate(inch, inch) - pdf6.setFillColor(colors.grey, alpha=0.6) - pdf6.setFont("Helvetica", 50) - pdf6.rotate(45) - pdf6.drawCentredString(400, 100, text) - pdf6.save() - - -def makepdf(): - pdf_file = input("PDF file: ") - watermark = 'watermark.pdf' - merged = "finalDraft.pdf" - with open(pdf_file, "rb") as input_file,\ - open(watermark, "rb") as watermark_file: - input_pdf = PdfFileReader(input_file) - watermark_pdf = PdfFileReader(watermark_file) - watermark_page = watermark_pdf.getPage(0) - - output = PdfFileWriter() - - for i in range(input_pdf.getNumPages()): - pdf_page = input_pdf.getPage(i) - pdf_page.mergePage(watermark_page) - output.addPage(pdf_page) - - with open(merged, "wb") as merged_file: - output.write(merged_file) - - -makeWatermark() -makepdf() +from reportlab.pdfgen import canvas +from reportlab.lib.units import inch +from reportlab.lib import colors +from reportlab.lib.pagesizes import A4 +from PyPDF2 import PdfFileReader, PdfFileWriter + + +print("Enter file names with its extenstion!") + + +def makeWatermark(): + text = input("Enter the watermark text here:") + pdf6 = canvas.Canvas("watermark.pdf", pagesize=A4) + pdf6.translate(inch, inch) + pdf6.setFillColor(colors.grey, alpha=0.6) + pdf6.setFont("Helvetica", 50) + pdf6.rotate(45) + pdf6.drawCentredString(400, 100, text) + pdf6.save() + + +def makepdf(): + pdf_file = input("PDF file: ") + watermark = 'watermark.pdf' + merged = "finalDraft.pdf" + with open(pdf_file, "rb") as input_file,\ + open(watermark, "rb") as watermark_file: + input_pdf = PdfFileReader(input_file) + watermark_pdf = PdfFileReader(watermark_file) + watermark_page = watermark_pdf.getPage(0) + + output = PdfFileWriter() + + for i in range(input_pdf.getNumPages()): + pdf_page = input_pdf.getPage(i) + pdf_page.mergePage(watermark_page) + output.addPage(pdf_page) + + with open(merged, "wb") as merged_file: + output.write(merged_file) + + +makeWatermark() +makepdf() diff --git a/watermark-maker/requirements.txt b/watermark-maker/requirements.txt index 1991006b3..54af5ff92 100644 --- a/watermark-maker/requirements.txt +++ b/watermark-maker/requirements.txt @@ -1,2 +1,2 @@ -PyPDF2==1.26.0 -reportlab==3.5.53 +PyPDF2==1.26.0 +reportlab==3.5.53 diff --git a/watermark_removal/README.md b/watermark_removal/README.md index 33d8a0ea8..70f8d4eee 100644 --- a/watermark_removal/README.md +++ b/watermark_removal/README.md @@ -1,23 +1,23 @@ -# Script to remove watermark from images and pdfs - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## How to use: -1. Call the function giving two arguments, the path to the images whose watermark is to be removed and the output path (where you want to store the cleaned images). (This script will remove the watermarks from all jpg images in the folder and store them into another folder "Cleaned") -
example :- -
```input_folder = "C:/User/Desktop"``` -
```output_folder = "C:/User/Desktop"``` -
```watermark_removal(input_file)``` - -2. If you have a pdf with watermarks to be removed, you need to call the pdf_to_jpg function. This takes two arguments the input folder (where your pdf exists) and the output folder(where the images of each page will be stored). -
example :- -
```input_folder = "C:/User/Desktop"``` -
```output_folder = "C:/User/Desktop"``` -
```pdf_to_jpg(input_folder, output_folder)``` - -3. After calling the pdf function you can call the watermark_removal function to remove the watermarks from the pdf. +# Script to remove watermark from images and pdfs + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## How to use: +1. Call the function giving two arguments, the path to the images whose watermark is to be removed and the output path (where you want to store the cleaned images). (This script will remove the watermarks from all jpg images in the folder and store them into another folder "Cleaned") +
example :- +
```input_folder = "C:/User/Desktop"``` +
```output_folder = "C:/User/Desktop"``` +
```watermark_removal(input_file)``` + +2. If you have a pdf with watermarks to be removed, you need to call the pdf_to_jpg function. This takes two arguments the input folder (where your pdf exists) and the output folder(where the images of each page will be stored). +
example :- +
```input_folder = "C:/User/Desktop"``` +
```output_folder = "C:/User/Desktop"``` +
```pdf_to_jpg(input_folder, output_folder)``` + +3. After calling the pdf function you can call the watermark_removal function to remove the watermarks from the pdf. diff --git a/watermark_removal/makefile b/watermark_removal/makefile index e78e53c81..7aafa604a 100644 --- a/watermark_removal/makefile +++ b/watermark_removal/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/watermark_removal/requirements.txt b/watermark_removal/requirements.txt index be28f4d6b..2cc4a83b5 100644 --- a/watermark_removal/requirements.txt +++ b/watermark_removal/requirements.txt @@ -1,4 +1,4 @@ -opencv-python -pdf2image -glob +opencv-python +pdf2image +glob numpy \ No newline at end of file diff --git a/watermark_removal/watermark_removal.py b/watermark_removal/watermark_removal.py index b0be09a06..fd8408800 100644 --- a/watermark_removal/watermark_removal.py +++ b/watermark_removal/watermark_removal.py @@ -1,29 +1,29 @@ -import numpy as np -import glob -import cv2 -from pdf2image import convert_from_path - - -def pdf_to_jpg(path_to_folder, output_path): - - for pdf in glob.glob(path_to_folder + "/*.pdf"): - pages = convert_from_path(pdf, 500) - i = 0 - - for page in pages: - page.save(output_path + "/image%04i.jpg" % i, 'JPEG') - i += 1 - - -def watermark_removal(path_to_folder, output_path): - i = 0 - alpha = 2.0 - beta = -160 - - for img1 in glob.glob(path_to_folder + "/*.jpg"): - originalimage = cv2.imread(img1) - imgGrayscale = cv2.cvtColor(originalimage, cv2.COLOR_BGR2GRAY) - imgcleaned = alpha * imgGrayscale + beta - imgcleaned = np.clip(imgcleaned, 0, 255).astype(np.uint8) - cv2.imwrite("Cleaned/image%03i.jpg" % i, imgcleaned) - i += 1 +import numpy as np +import glob +import cv2 +from pdf2image import convert_from_path + + +def pdf_to_jpg(path_to_folder, output_path): + + for pdf in glob.glob(path_to_folder + "/*.pdf"): + pages = convert_from_path(pdf, 500) + i = 0 + + for page in pages: + page.save(output_path + "/image%04i.jpg" % i, 'JPEG') + i += 1 + + +def watermark_removal(path_to_folder, output_path): + i = 0 + alpha = 2.0 + beta = -160 + + for img1 in glob.glob(path_to_folder + "/*.jpg"): + originalimage = cv2.imread(img1) + imgGrayscale = cv2.cvtColor(originalimage, cv2.COLOR_BGR2GRAY) + imgcleaned = alpha * imgGrayscale + beta + imgcleaned = np.clip(imgcleaned, 0, 255).astype(np.uint8) + cv2.imwrite("Cleaned/image%03i.jpg" % i, imgcleaned) + i += 1 diff --git a/weather_informer/README.md b/weather_informer/README.md index d1313b79b..f064940d3 100644 --- a/weather_informer/README.md +++ b/weather_informer/README.md @@ -1,27 +1,27 @@ -# Weather - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -Cli used to gather weather information. It is a basic wrapper around [wttr.in](http://wttr.in/)'s http interface. - -```shell -user@computer:~$ python3 weather.py -Venice, Italy - - \ / Sunny - .-. 10 Β°C - ― ( ) ― β†– 0 km/h - `-’ 10 km - / \ 0.0 mm -``` - -Use the ```--help``` option to learn all the options available. - -### Dependencies -* [Requests](https://requests.readthedocs.io/) -* [Click](https://click.palletsprojects.com/) +# Weather + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +Cli used to gather weather information. It is a basic wrapper around [wttr.in](http://wttr.in/)'s http interface. + +```shell +user@computer:~$ python3 weather.py +Venice, Italy + + \ / Sunny + .-. 10 Β°C + ― ( ) ― β†– 0 km/h + `-’ 10 km + / \ 0.0 mm +``` + +Use the ```--help``` option to learn all the options available. + +### Dependencies +* [Requests](https://requests.readthedocs.io/) +* [Click](https://click.palletsprojects.com/) diff --git a/weather_informer/makefile b/weather_informer/makefile index e78e53c81..7aafa604a 100644 --- a/weather_informer/makefile +++ b/weather_informer/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/weather_informer/requirements.txt b/weather_informer/requirements.txt index 0d8c96eb7..5eda145e9 100644 --- a/weather_informer/requirements.txt +++ b/weather_informer/requirements.txt @@ -1,2 +1,2 @@ -click -requests +click +requests diff --git a/weather_informer/weather.py b/weather_informer/weather.py index 5fb8f684e..1a8a18829 100644 --- a/weather_informer/weather.py +++ b/weather_informer/weather.py @@ -1,57 +1,57 @@ -import click -import locale -import requests - - -# # # # # # # # # # # # # # # # # Constants # # # # # # # # # # # # # # # # # # -URL = 'https://wttr.in/{loc}?{fore}{metric}{col}AF&lang={lang}&format={format}' -ERR_MSG = 'Error: could not reach the service. Status code: {}.' -CONN_ERR = 'Error: connection not available.' -FORECAST_HELP = 'Shows also the forecasts for today and tomorrow.' -METRIC_HELP = 'Use the International System of Units.' -USCS_HELP = 'Use the United States Customary Units.' -LANG_HELP = 'Choose preferred language. ISO 639-1 code.' -COLORS_HELP = 'Keep or remove terminal sequences for colors. Default is keep.' -ONELINE_HELP = 'Shorter summary that fits in one line and uses emojis.' -# # # # # # # # # # # # # # # # # #Β #Β #Β #Β # # # # # # # # # # # # # # # # # # # - - -def default_lang(): - """ - Gets default language ISO 639-1 code. - """ - return locale.getdefaultlocale()[0][:2] - - -@click.command(context_settings=dict(help_option_names=['-h', '--help'])) -@click.argument('location', default='') -@click.option('-f', '--forecast', is_flag=True, help=FORECAST_HELP) -@click.option('-m', '--metric', 'metric', flag_value='m', help=METRIC_HELP) -@click.option('-u', '--uscs', 'metric', flag_value='u', help=USCS_HELP) -@click.option('-l', '--language', default=default_lang(), help=LANG_HELP) -@click.option('--colors/--no-colors', default='True', help=COLORS_HELP) -@click.option('-o', '--one-line', is_flag=True, help=ONELINE_HELP) -def wttr(location, forecast, metric, language, colors, one_line): - """ - Cli built using wttr.in API - """ - url = URL.format( - loc=location, - fore='2' if forecast else '0', - metric=metric if metric is not None else '', - lang=language, - col='' if colors else 'T', - format='4' if one_line else '' - ) - try: - response = requests.get(url) - if response.ok: - print(response.text) - else: - print(ERR_MSG.format(response.status_code)) - except requests.exceptions.ConnectionError: - print(CONN_ERR) - - -if __name__ == '__main__': - wttr() +import click +import locale +import requests + + +# # # # # # # # # # # # # # # # # Constants # # # # # # # # # # # # # # # # # # +URL = 'https://wttr.in/{loc}?{fore}{metric}{col}AF&lang={lang}&format={format}' +ERR_MSG = 'Error: could not reach the service. Status code: {}.' +CONN_ERR = 'Error: connection not available.' +FORECAST_HELP = 'Shows also the forecasts for today and tomorrow.' +METRIC_HELP = 'Use the International System of Units.' +USCS_HELP = 'Use the United States Customary Units.' +LANG_HELP = 'Choose preferred language. ISO 639-1 code.' +COLORS_HELP = 'Keep or remove terminal sequences for colors. Default is keep.' +ONELINE_HELP = 'Shorter summary that fits in one line and uses emojis.' +# # # # # # # # # # # # # # # # # #Β #Β #Β #Β # # # # # # # # # # # # # # # # # # # + + +def default_lang(): + """ + Gets default language ISO 639-1 code. + """ + return locale.getdefaultlocale()[0][:2] + + +@click.command(context_settings=dict(help_option_names=['-h', '--help'])) +@click.argument('location', default='') +@click.option('-f', '--forecast', is_flag=True, help=FORECAST_HELP) +@click.option('-m', '--metric', 'metric', flag_value='m', help=METRIC_HELP) +@click.option('-u', '--uscs', 'metric', flag_value='u', help=USCS_HELP) +@click.option('-l', '--language', default=default_lang(), help=LANG_HELP) +@click.option('--colors/--no-colors', default='True', help=COLORS_HELP) +@click.option('-o', '--one-line', is_flag=True, help=ONELINE_HELP) +def wttr(location, forecast, metric, language, colors, one_line): + """ + Cli built using wttr.in API + """ + url = URL.format( + loc=location, + fore='2' if forecast else '0', + metric=metric if metric is not None else '', + lang=language, + col='' if colors else 'T', + format='4' if one_line else '' + ) + try: + response = requests.get(url) + if response.ok: + print(response.text) + else: + print(ERR_MSG.format(response.status_code)) + except requests.exceptions.ConnectionError: + print(CONN_ERR) + + +if __name__ == '__main__': + wttr() diff --git a/website_blocker/README.md b/website_blocker/README.md index 566a5d6a6..2ec2508b5 100644 --- a/website_blocker/README.md +++ b/website_blocker/README.md @@ -1,15 +1,15 @@ -# Website Blocker -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -Block Websites on your system using this script - -* Simple Menu to add sites to block -* Restore changes when you exit from script - -# Note -The webisites you have blocked using this script will only be restored/unblocked if you property exit from the script using the Website Blocker CLI menu if you force close the terminal window or the app. +# Website Blocker +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +Block Websites on your system using this script + +* Simple Menu to add sites to block +* Restore changes when you exit from script + +# Note +The webisites you have blocked using this script will only be restored/unblocked if you property exit from the script using the Website Blocker CLI menu if you force close the terminal window or the app. diff --git a/website_blocker/website_blocker.py b/website_blocker/website_blocker.py index 65e508a8e..d469fbb6c 100644 --- a/website_blocker/website_blocker.py +++ b/website_blocker/website_blocker.py @@ -1,119 +1,119 @@ -import ctypes -import sys -from sys import platform -import os -from os import system -from elevate import elevate - - -class Blocker: - hosts_path = '' - redirect = "127.0.0.1" - website_list = [] - os_number = 0 - exit_blocker = False - - def __init__(self, path, os_num): - self.hosts_path = r"" + path - self.os_number = os_num - - print("Blocked Websites (^v^)") - print("# None") - - def blocker_menu(self): - if self.os_number == 2: - self.duplicate_host_file() - - while not self.exit_blocker: - print("********************") - print("WEBSITE BLOCKER MENU") - print("********************") - print("Type '+' to add Website") - print("Type 'exit' to stop the blocker") - user_input = input("Enter here: ") - - if user_input == '+': - self.add_websites() - - print("Blocked Websites (^v^)") - for website in self.website_list: - print("# " + website) - elif user_input == 'exit': - print("Restoring Every change.....") - self.restore_host_file() - print("Thanks you using") - self.exit_blocker = True - else: - print("Invalid Input Try Again") - - def restore_host_file(self): - with open(self.hosts_path, 'r+') as file: - content = file.readlines() - file.seek(0) - for line in content: - if not any(website in line for website in self.website_list): - file.write(line) - - file.truncate() - file.close() - - def duplicate_host_file(self): - # to create a copy of host file specially for windows if script not working - pass - - def add_websites(self): - print("Enter a website url to add like 'www.facebook.com or facebook.com'") - user_input = input("Enter URL Here: ") - self.website_list.append(user_input) - with open(self.hosts_path, 'r+') as file: - file.write(self.redirect + " " + user_input + "\n") - - file.close() - - def clear_console(self): - if self.os_number == 2: - _ = system('cls') - else: - _ = system('clear') - - -def get_os(): - if platform == "linux" or platform == "linux2": - # linux - return 0 - elif platform == "darwin": - # OS X - return 1 - elif platform == "win32": - # Windows... - return 2 - - -def driver(): - if get_os() == 2: - if ctypes.windll.shell32.IsUserAnAdmin() == 0: - ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1) - else: - if os.getuid() == 0: - elevate(graphical=False) - - print("Running script with Root/Admin privileges. AWESOME!!") - - os_number = get_os() - - if os_number == 2: - print("OS: Windows") - website_blocker = Blocker(r"C:\Windows\System32\drivers\etc\hosts", os_number) - website_blocker.blocker_menu() - elif os_number == 1: - print("OS: OS X") - website_blocker = Blocker("/etc/hosts", os_number) - website_blocker.blocker_menu() - elif os_number == 0: - print("OS: Linux") - website_blocker = Blocker("/etc/hosts", os_number) - website_blocker.blocker_menu() - - -if __name__ == "__main__": - driver() +import ctypes +import sys +from sys import platform +import os +from os import system +from elevate import elevate + + +class Blocker: + hosts_path = '' + redirect = "127.0.0.1" + website_list = [] + os_number = 0 + exit_blocker = False + + def __init__(self, path, os_num): + self.hosts_path = r"" + path + self.os_number = os_num + + print("Blocked Websites (^v^)") + print("# None") + + def blocker_menu(self): + if self.os_number == 2: + self.duplicate_host_file() + + while not self.exit_blocker: + print("********************") + print("WEBSITE BLOCKER MENU") + print("********************") + print("Type '+' to add Website") + print("Type 'exit' to stop the blocker") + user_input = input("Enter here: ") + + if user_input == '+': + self.add_websites() + + print("Blocked Websites (^v^)") + for website in self.website_list: + print("# " + website) + elif user_input == 'exit': + print("Restoring Every change.....") + self.restore_host_file() + print("Thanks you using") + self.exit_blocker = True + else: + print("Invalid Input Try Again") + + def restore_host_file(self): + with open(self.hosts_path, 'r+') as file: + content = file.readlines() + file.seek(0) + for line in content: + if not any(website in line for website in self.website_list): + file.write(line) + + file.truncate() + file.close() + + def duplicate_host_file(self): + # to create a copy of host file specially for windows if script not working + pass + + def add_websites(self): + print("Enter a website url to add like 'www.facebook.com or facebook.com'") + user_input = input("Enter URL Here: ") + self.website_list.append(user_input) + with open(self.hosts_path, 'r+') as file: + file.write(self.redirect + " " + user_input + "\n") + + file.close() + + def clear_console(self): + if self.os_number == 2: + _ = system('cls') + else: + _ = system('clear') + + +def get_os(): + if platform == "linux" or platform == "linux2": + # linux + return 0 + elif platform == "darwin": + # OS X + return 1 + elif platform == "win32": + # Windows... + return 2 + + +def driver(): + if get_os() == 2: + if ctypes.windll.shell32.IsUserAnAdmin() == 0: + ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1) + else: + if os.getuid() == 0: + elevate(graphical=False) + + print("Running script with Root/Admin privileges. AWESOME!!") + + os_number = get_os() + + if os_number == 2: + print("OS: Windows") + website_blocker = Blocker(r"C:\Windows\System32\drivers\etc\hosts", os_number) + website_blocker.blocker_menu() + elif os_number == 1: + print("OS: OS X") + website_blocker = Blocker("/etc/hosts", os_number) + website_blocker.blocker_menu() + elif os_number == 0: + print("OS: Linux") + website_blocker = Blocker("/etc/hosts", os_number) + website_blocker.blocker_menu() + + +if __name__ == "__main__": + driver() diff --git a/whatsapp_bot/README.md b/whatsapp_bot/README.md index 4fa0d88b8..04bf11492 100644 --- a/whatsapp_bot/README.md +++ b/whatsapp_bot/README.md @@ -1,12 +1,12 @@ -# Whatsapp Bot -## Perform Operation like -1. Put your details -2. connect with internet -3. Pass your message - -# To run app -- Create virtual Environment -- Install requirements -`pip install requirements.txt` -- run app -`python main.py` +# Whatsapp Bot +## Perform Operation like +1. Put your details +2. connect with internet +3. Pass your message + +# To run app +- Create virtual Environment +- Install requirements +`pip install requirements.txt` +- run app +`python main.py` diff --git a/whatsapp_bot/whatsapp.py b/whatsapp_bot/whatsapp.py index baffe4373..759033791 100644 --- a/whatsapp_bot/whatsapp.py +++ b/whatsapp_bot/whatsapp.py @@ -1,12 +1,12 @@ -import pywhatkit -from datetime import datetime - -now = datetime.now() - -chour = now.strftime("%H") -mobile = input('Enter Mobile No of Receiver : ') -message = input('Enter Message you wanna send : ') -hour = int(chour) + int(input('Enter hour : ')) -minute = int(input('Enter minute : ')) - -pywhatkit.sendwhatmsg(mobile, message, hour, minute) +import pywhatkit +from datetime import datetime + +now = datetime.now() + +chour = now.strftime("%H") +mobile = input('Enter Mobile No of Receiver : ') +message = input('Enter Message you wanna send : ') +hour = int(chour) + int(input('Enter hour : ')) +minute = int(input('Enter minute : ')) + +pywhatkit.sendwhatmsg(mobile, message, hour, minute) diff --git a/wifi_passwords/README.md b/wifi_passwords/README.md index d98827e4a..ce146d3b6 100644 --- a/wifi_passwords/README.md +++ b/wifi_passwords/README.md @@ -1,16 +1,16 @@ -# Wifi Passwords -A python script used to lookup all passwords of the connected wifi SSIDs. - -## Modules Used -- subprocess -- platform - -## Support and version -The script requires **python3 or above** and currently supports Windows and Linux platforms, - -## How to use -``` -python3 wifi_passwords.py -``` -**sudo** permission required to run the script on Linux platforms, - +# Wifi Passwords +A python script used to lookup all passwords of the connected wifi SSIDs. + +## Modules Used +- subprocess +- platform + +## Support and version +The script requires **python3 or above** and currently supports Windows and Linux platforms, + +## How to use +``` +python3 wifi_passwords.py +``` +**sudo** permission required to run the script on Linux platforms, + diff --git a/wifi_passwords/wifi_passwords.py b/wifi_passwords/wifi_passwords.py index 2c14d6a18..babdc8893 100644 --- a/wifi_passwords/wifi_passwords.py +++ b/wifi_passwords/wifi_passwords.py @@ -1,91 +1,91 @@ -import subprocess -import platform -import locale - - -def exec_linux(): - cmd = 'ls /etc/NetworkManager/system-connections' - wifi_ssids = subprocess.run(cmd, capture_output=True, shell=True) - list_ssids = wifi_ssids.stdout.decode().split('\n') - - list_cmds = list() - - for i in list_ssids: - if i != '': - list_cmds.append(f' "/etc/NetworkManager/system-connections/{i}"') - - cat_cmds = 'sudo cat ' + ' '.join(list_cmds) + ' | grep psk=' - - print( - 'Requires sudo permission to read the wifi passwords, ' - + 'if you want you can see the command, [Y]', end=' ') - if input().lower() == 'y': - print(f'\n{cat_cmds}\n') - - passwords = subprocess.run(cat_cmds, capture_output=True, shell=True) - - psks = passwords.stdout.decode().split('\n') - - if len(psks) != len(list_cmds): - print('\nInvalid password!\n') - return 0 - - print('\n List of Wifi SSIDs with passwords\n') - for i in zip(list_ssids, psks): - print(f'\t{i[0]} : {i[1][4:]}') - - -def exec_windows(): - default_lang = locale.getdefaultlocale()[0] - - KEYWORDS = { - "fr_FR": ['profil tous les utilisateurs', 'Contenu'], - "en_GB": ['all user profile', 'Key Content'], - "en_US": ['all user profile', 'Key Content'], - "en_IN": ['all user profile', 'Key Content'] - } - - wifi_ssids = subprocess.run( - 'netsh wlan show profile', - capture_output=True, - shell=True - ) - list_ssids = [ - i.strip().lower() for i in wifi_ssids.stdout.decode("ISO-8859-1") - .split('\r\n') - ] - - cmds = list() - - for ssid in list_ssids: - if ssid.startswith(KEYWORDS[default_lang][0]): - cmds.append(ssid.split(':')[1].strip()) - - output = list() - for cmd in cmds: - cat_cmd = f'netsh wlan show profile "{cmd}" key=clear' - cat_cmd = subprocess.run(cat_cmd, capture_output=True, shell=True) - out = cat_cmd.stdout.decode("ISO-8859-1").split('\r\n') - for key in out: - if key.strip().startswith(KEYWORDS[default_lang][1]): - temp_key = key.split(': ') - if len(temp_key) == 2: - output.append((cmd, temp_key[1])) - break - else: - output.append((cmd, '')) - break - - print('\n List of Wifi SSIDs with passwords\n') - for i in output: - print(f'\t{i[0]} : {i[1]}') - - -if __name__ == '__main__': - current_platform = platform.system().lower() - if current_platform == 'linux': - exec_linux() - elif current_platform == 'windows': - exec_windows() - else: - print('Apologies, only supports Linux and Windows') +import subprocess +import platform +import locale + + +def exec_linux(): + cmd = 'ls /etc/NetworkManager/system-connections' + wifi_ssids = subprocess.run(cmd, capture_output=True, shell=True) + list_ssids = wifi_ssids.stdout.decode().split('\n') + + list_cmds = list() + + for i in list_ssids: + if i != '': + list_cmds.append(f' "/etc/NetworkManager/system-connections/{i}"') + + cat_cmds = 'sudo cat ' + ' '.join(list_cmds) + ' | grep psk=' + + print( + 'Requires sudo permission to read the wifi passwords, ' + + 'if you want you can see the command, [Y]', end=' ') + if input().lower() == 'y': + print(f'\n{cat_cmds}\n') + + passwords = subprocess.run(cat_cmds, capture_output=True, shell=True) + + psks = passwords.stdout.decode().split('\n') + + if len(psks) != len(list_cmds): + print('\nInvalid password!\n') + return 0 + + print('\n List of Wifi SSIDs with passwords\n') + for i in zip(list_ssids, psks): + print(f'\t{i[0]} : {i[1][4:]}') + + +def exec_windows(): + default_lang = locale.getdefaultlocale()[0] + + KEYWORDS = { + "fr_FR": ['profil tous les utilisateurs', 'Contenu'], + "en_GB": ['all user profile', 'Key Content'], + "en_US": ['all user profile', 'Key Content'], + "en_IN": ['all user profile', 'Key Content'] + } + + wifi_ssids = subprocess.run( + 'netsh wlan show profile', + capture_output=True, + shell=True + ) + list_ssids = [ + i.strip().lower() for i in wifi_ssids.stdout.decode("ISO-8859-1") + .split('\r\n') + ] + + cmds = list() + + for ssid in list_ssids: + if ssid.startswith(KEYWORDS[default_lang][0]): + cmds.append(ssid.split(':')[1].strip()) + + output = list() + for cmd in cmds: + cat_cmd = f'netsh wlan show profile "{cmd}" key=clear' + cat_cmd = subprocess.run(cat_cmd, capture_output=True, shell=True) + out = cat_cmd.stdout.decode("ISO-8859-1").split('\r\n') + for key in out: + if key.strip().startswith(KEYWORDS[default_lang][1]): + temp_key = key.split(': ') + if len(temp_key) == 2: + output.append((cmd, temp_key[1])) + break + else: + output.append((cmd, '')) + break + + print('\n List of Wifi SSIDs with passwords\n') + for i in output: + print(f'\t{i[0]} : {i[1]}') + + +if __name__ == '__main__': + current_platform = platform.system().lower() + if current_platform == 'linux': + exec_linux() + elif current_platform == 'windows': + exec_windows() + else: + print('Apologies, only supports Linux and Windows') diff --git a/wikipedia_searchsave/README.md b/wikipedia_searchsave/README.md index def6a79c8..f51e9cf1f 100644 --- a/wikipedia_searchsave/README.md +++ b/wikipedia_searchsave/README.md @@ -1,53 +1,53 @@ -# Wikipedia Search & Save as PDF -A python script that allows the user to search for articles in Wikipedia and saves the summary of the article as a PDF file. - -## Modules Used - -- argparse -- wikipedia -- fpdf - -## Requirements -We need to install the wikipedia and fpdf module. To install the modules type the following into the terminal: -```bash -pip install wikipedia -pip install fpdf -``` - -Recommended: Install the module after creating a virtual environment. - -## Execution -- To run the program, type the following command into your terminal - -```bash -python wikipedia_search_and_save.py -s [Your search query] -``` -Example -```bash -python wikipedia_search_and_save.py -s "Computers" -``` -- Alternatively, type the following command into your terminal - -```bash -python wikipedia_search_and_save.py --search [Your search query] -``` -Example -```bash -python wikipedia_search_and_save.py --search "Mobile Phones" -``` - -As an example, we have searched for "Computers" or "Mobile Phones". -After the search is completed successfully, the article is saved as "Computers.pdf" or "Mobile Phones.pdf" (based on which topic you have searched for) and the program gives the following output on the terminal. -```bash -[+] Your file was successfully saved. -``` -- For help, type the following command into your terminal - -```bash -python wikipedia_search_and_save.py --help -``` -Or -```bash -python wikipedia_search_and_save.py -h -``` +# Wikipedia Search & Save as PDF +A python script that allows the user to search for articles in Wikipedia and saves the summary of the article as a PDF file. + +## Modules Used + +- argparse +- wikipedia +- fpdf + +## Requirements +We need to install the wikipedia and fpdf module. To install the modules type the following into the terminal: +```bash +pip install wikipedia +pip install fpdf +``` + +Recommended: Install the module after creating a virtual environment. + +## Execution +- To run the program, type the following command into your terminal + +```bash +python wikipedia_search_and_save.py -s [Your search query] +``` +Example +```bash +python wikipedia_search_and_save.py -s "Computers" +``` +- Alternatively, type the following command into your terminal + +```bash +python wikipedia_search_and_save.py --search [Your search query] +``` +Example +```bash +python wikipedia_search_and_save.py --search "Mobile Phones" +``` + +As an example, we have searched for "Computers" or "Mobile Phones". +After the search is completed successfully, the article is saved as "Computers.pdf" or "Mobile Phones.pdf" (based on which topic you have searched for) and the program gives the following output on the terminal. +```bash +[+] Your file was successfully saved. +``` +- For help, type the following command into your terminal + +```bash +python wikipedia_search_and_save.py --help +``` +Or +```bash +python wikipedia_search_and_save.py -h +``` Note: The file temp.txt saves the content of the search result temporarily. The file is emptied after the content is saved as PDF file. \ No newline at end of file diff --git a/wikipedia_searchsave/wikipedia_search_and_save.py b/wikipedia_searchsave/wikipedia_search_and_save.py index c09cfdc16..bfc47ce14 100644 --- a/wikipedia_searchsave/wikipedia_search_and_save.py +++ b/wikipedia_searchsave/wikipedia_search_and_save.py @@ -1,77 +1,77 @@ -import argparse -import wikipedia -from fpdf import FPDF - - -class PDF(FPDF): - def chapter_title(self, label): - # Arial 12 - self.set_font('Arial', '', 12) - # Background color - self.set_fill_color(200, 220, 255) - # Title - self.cell(0, 6, '%s' % (label), 0, 1, 'L', 1) - # Line break - self.ln(4) - - def chapter_body(self, file_name): - # Read text file - with open(file_name, 'rb') as fh: - txt = fh.read().decode('latin-1') - # Times 12 - self.set_font('Times', '', 12) - # Output justified text - self.multi_cell(0, 5, txt) - # Line break - self.ln() - - def print_chapter(self, title, file_name): - self.add_page() - self.chapter_title(title) - self.chapter_body(file_name) - - -def wikipedia_search(user_input): - query = wikipedia.page(user_input) - - # Writing the search result in a temp file - file = open('temp.txt', 'w') - # write() - it used to write direct text to the file - file.write(query.summary) - # closing the file - file.close() - - # variable pdf - pdf = PDF() - # declaring our file name - pdf_file_name = user_input + ".pdf" - # writing the content to a pdf file - pdf.print_chapter(query.original_title, 'temp.txt') - # saving the file in our computer - pdf.output(pdf_file_name, 'F') - - # Clearing our temp file - open("temp.txt", "w").close() - - -def main(): - # Initialize parser - parser = argparse.ArgumentParser() - # Adding optional argument - parser.add_argument("-s", "--search", - help="search your query") - # parser.add_argument("-m", "--message", help="insert your message here") - - # Read arguments from command line - args = parser.parse_args() - if args.search is None: - print("[-] No arguments were provided.") - print("[x] For help: 'python wikipedia_search_and_save.py --help'") - - if args.search: - wikipedia_search(args.search) - print("[+] Your file was successfully saved.") - - -if __name__ == "__main__": - main() +import argparse +import wikipedia +from fpdf import FPDF + + +class PDF(FPDF): + def chapter_title(self, label): + # Arial 12 + self.set_font('Arial', '', 12) + # Background color + self.set_fill_color(200, 220, 255) + # Title + self.cell(0, 6, '%s' % (label), 0, 1, 'L', 1) + # Line break + self.ln(4) + + def chapter_body(self, file_name): + # Read text file + with open(file_name, 'rb') as fh: + txt = fh.read().decode('latin-1') + # Times 12 + self.set_font('Times', '', 12) + # Output justified text + self.multi_cell(0, 5, txt) + # Line break + self.ln() + + def print_chapter(self, title, file_name): + self.add_page() + self.chapter_title(title) + self.chapter_body(file_name) + + +def wikipedia_search(user_input): + query = wikipedia.page(user_input) + + # Writing the search result in a temp file + file = open('temp.txt', 'w') + # write() - it used to write direct text to the file + file.write(query.summary) + # closing the file + file.close() + + # variable pdf + pdf = PDF() + # declaring our file name + pdf_file_name = user_input + ".pdf" + # writing the content to a pdf file + pdf.print_chapter(query.original_title, 'temp.txt') + # saving the file in our computer + pdf.output(pdf_file_name, 'F') + + # Clearing our temp file + open("temp.txt", "w").close() + + +def main(): + # Initialize parser + parser = argparse.ArgumentParser() + # Adding optional argument + parser.add_argument("-s", "--search", + help="search your query") + # parser.add_argument("-m", "--message", help="insert your message here") + + # Read arguments from command line + args = parser.parse_args() + if args.search is None: + print("[-] No arguments were provided.") + print("[x] For help: 'python wikipedia_search_and_save.py --help'") + + if args.search: + wikipedia_search(args.search) + print("[+] Your file was successfully saved.") + + +if __name__ == "__main__": + main() diff --git a/word_cloud/README.md b/word_cloud/README.md index 14fc40200..a6f049507 100644 --- a/word_cloud/README.md +++ b/word_cloud/README.md @@ -1,19 +1,19 @@ -# Script to create wordcloud for a text file - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -## How to use: -1. Make the directory structure as shown below: -
. -
β”œβ”€β”€ word_cloud.py -
└── text_file.txt - -2. Call the function giving two arguments, the path to the text file and the title of the plot (which is optional) -
example :- -
```wordcloud("./text_file.txt, title = "xyz")``` - +# Script to create wordcloud for a text file + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +## How to use: +1. Make the directory structure as shown below: +
. +
β”œβ”€β”€ word_cloud.py +
└── text_file.txt + +2. Call the function giving two arguments, the path to the text file and the title of the plot (which is optional) +
example :- +
```wordcloud("./text_file.txt, title = "xyz")``` + diff --git a/word_cloud/makefile b/word_cloud/makefile index e78e53c81..7aafa604a 100644 --- a/word_cloud/makefile +++ b/word_cloud/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/word_cloud/requirements.txt b/word_cloud/requirements.txt index 6b5748ecd..4c4ec6ddc 100644 --- a/word_cloud/requirements.txt +++ b/word_cloud/requirements.txt @@ -1,2 +1,2 @@ -wordcloud +wordcloud matplotlib \ No newline at end of file diff --git a/word_cloud/word_cloud.py b/word_cloud/word_cloud.py index 635cc8b23..28bea898b 100644 --- a/word_cloud/word_cloud.py +++ b/word_cloud/word_cloud.py @@ -1,24 +1,24 @@ -from wordcloud import WordCloud, STOPWORDS -import matplotlib.pyplot as plt -stopwords = set(STOPWORDS) - - -def wordcloud(path, title=None): - data = open(path, 'r').read().lower() - wordcloud = WordCloud( - background_color='white', - stopwords=stopwords, - max_words=200, - max_font_size=40, - scale=3, - random_state=1 - ).generate(str(data)) - - fig = plt.figure(1, figsize=(12, 12)) - plt.axis('off') - if title: - fig.suptitle(title, fontsize=20) - fig.subplots_adjust(top=2.3) - - plt.imshow(wordcloud) - plt.show() +from wordcloud import WordCloud, STOPWORDS +import matplotlib.pyplot as plt +stopwords = set(STOPWORDS) + + +def wordcloud(path, title=None): + data = open(path, 'r').read().lower() + wordcloud = WordCloud( + background_color='white', + stopwords=stopwords, + max_words=200, + max_font_size=40, + scale=3, + random_state=1 + ).generate(str(data)) + + fig = plt.figure(1, figsize=(12, 12)) + plt.axis('off') + if title: + fig.suptitle(title, fontsize=20) + fig.subplots_adjust(top=2.3) + + plt.imshow(wordcloud) + plt.show() diff --git a/youtube_clipper/README.md b/youtube_clipper/README.md index 7edc7c13e..18e812f1b 100644 --- a/youtube_clipper/README.md +++ b/youtube_clipper/README.md @@ -1,55 +1,55 @@ -# Youtube Clipper -Youtube Clipper downloads a video clip from youtube from starting time to ending time told by the user without downloading the whole video. -## Installing the Dependencies: -Install these two packages: ffmpeg and youtube_dl - -For youtube_dl type the following command in terminal: -```cmd -pip install youtube_dl -``` -For ffmpeg install it according to your OS - -After installing them check whether both of them have been installed correctly by just typing 'ffmpeg' and 'youtube_dl' on terminal - -## Steps to download the video -Run the script ```youtube_clip.py``` on terminal -``` -python youtube_clip.py -``` -After executing the script you will be asked for the link of the video, start time of the clip, end time of the clip and name of the output video - -First you will be asked about the link of the youtube video you want to download as shown below: -``` -Enter the Youtube video link: -``` -Sample Input: -``` -Enter the Youtube video link: https://www.youtube.com/watch?v=hlWiI4xVXKY&ab_channel=SoothingRelaxation -``` -Now you will be asked to enter the start time of your video clip as shown below: -``` -Enter start time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: -``` -Sample Input: -``` -Enter start time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: 1:23 -``` -Now you will be asked to enter the end time of your video clip as shown below: -``` -Enter end time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: -``` -Sample Input: -``` -Enter end time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: 1:23:45 -``` -Then you will be asked to name your output video file as shown below: -``` -Enter your output video name: -``` -Sample Input: -``` -Enter your output video name: Relaxing_Video -``` -Now your youtube video will be downloaded from start time to end time with the name of output file name you gave. - -## Note: This script works only for videos with mp4 format as most of the youtube videos have that link +# Youtube Clipper +Youtube Clipper downloads a video clip from youtube from starting time to ending time told by the user without downloading the whole video. +## Installing the Dependencies: +Install these two packages: ffmpeg and youtube_dl + +For youtube_dl type the following command in terminal: +```cmd +pip install youtube_dl +``` +For ffmpeg install it according to your OS + +After installing them check whether both of them have been installed correctly by just typing 'ffmpeg' and 'youtube_dl' on terminal + +## Steps to download the video +Run the script ```youtube_clip.py``` on terminal +``` +python youtube_clip.py +``` +After executing the script you will be asked for the link of the video, start time of the clip, end time of the clip and name of the output video + +First you will be asked about the link of the youtube video you want to download as shown below: +``` +Enter the Youtube video link: +``` +Sample Input: +``` +Enter the Youtube video link: https://www.youtube.com/watch?v=hlWiI4xVXKY&ab_channel=SoothingRelaxation +``` +Now you will be asked to enter the start time of your video clip as shown below: +``` +Enter start time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: +``` +Sample Input: +``` +Enter start time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: 1:23 +``` +Now you will be asked to enter the end time of your video clip as shown below: +``` +Enter end time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: +``` +Sample Input: +``` +Enter end time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: 1:23:45 +``` +Then you will be asked to name your output video file as shown below: +``` +Enter your output video name: +``` +Sample Input: +``` +Enter your output video name: Relaxing_Video +``` +Now your youtube video will be downloaded from start time to end time with the name of output file name you gave. + +## Note: This script works only for videos with mp4 format as most of the youtube videos have that link diff --git a/youtube_clipper/requirements.txt b/youtube_clipper/requirements.txt index 2ca1d49c9..01f68f08c 100644 --- a/youtube_clipper/requirements.txt +++ b/youtube_clipper/requirements.txt @@ -1,2 +1,2 @@ -youtube_dl -ffmpeg +youtube_dl +ffmpeg diff --git a/youtube_clipper/youtube_clip.py b/youtube_clipper/youtube_clip.py index 51e65b3d7..e287bf421 100644 --- a/youtube_clipper/youtube_clip.py +++ b/youtube_clipper/youtube_clip.py @@ -1,60 +1,60 @@ -# importing the packages -import subprocess - - -# function that returns time in seconds -def time_manipulation(time): - if len(time) == 1: - time = "00:00:0" + time - if len(time) == 2: - time = "00:00:" + time - if len(time) == 4: - time = "00:0" + time - if len(time) == 5: - time = "00:" + time - if len(time) == 7: - time = "0" + time - h, m, s = time.split(':') - time = int(h) * 3600 + int(m) * 60 + int(s) - return time - - -youtube_link = input("Enter the Youtube video link: ") -start_time = input("Enter start time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: ") -start_time = time_manipulation(start_time) # start time in seconds -end_time = input("Enter end time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: ") -end_time = time_manipulation(end_time) # end time in seconds -duration = end_time - start_time -Output_file_name = input("Enter your output video name: ") -Output_file_name = Output_file_name + '.mp4' - -# Error-1 -if duration <= 0: - print("ERROR: Start time should be less than End time") - quit() - -# calculating the length of youtube video in seconds -duration_of_video = subprocess.run(["youtube-dl", "--no-check-certificate", "--get-duration", youtube_link], - stdout=subprocess.PIPE, text=True) -video_length = duration_of_video.stdout -video_length = video_length[:-1] -video_length = time_manipulation(video_length) # video length in seconds - -# Error-2 -if end_time > video_length: - print("ERROR: End time should be less than the Length of video") - quit() - -# removing the channel name from link if it is present -for ch in youtube_link: - if ch == '&': - youtube_link = youtube_link[:youtube_link.index(ch)] - -# getting the download link of the youtube video -download_link = subprocess.run(["youtube-dl", "--no-check-certificate", "-f", "22", "--get-url", youtube_link], - stdout=subprocess.PIPE, text=True) -link = download_link.stdout - -# downloading the video from start_time to end_time -subprocess.run(["ffmpeg", "-ss", str(start_time), "-i", link, "-t", str(duration), "-c:v", "copy", "-c:a", - "copy", Output_file_name]) +# importing the packages +import subprocess + + +# function that returns time in seconds +def time_manipulation(time): + if len(time) == 1: + time = "00:00:0" + time + if len(time) == 2: + time = "00:00:" + time + if len(time) == 4: + time = "00:0" + time + if len(time) == 5: + time = "00:" + time + if len(time) == 7: + time = "0" + time + h, m, s = time.split(':') + time = int(h) * 3600 + int(m) * 60 + int(s) + return time + + +youtube_link = input("Enter the Youtube video link: ") +start_time = input("Enter start time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: ") +start_time = time_manipulation(start_time) # start time in seconds +end_time = input("Enter end time of the video clip in HH:MM:SS|H:MM:SS|MM:SS|M:SS|SS|S format: ") +end_time = time_manipulation(end_time) # end time in seconds +duration = end_time - start_time +Output_file_name = input("Enter your output video name: ") +Output_file_name = Output_file_name + '.mp4' + +# Error-1 +if duration <= 0: + print("ERROR: Start time should be less than End time") + quit() + +# calculating the length of youtube video in seconds +duration_of_video = subprocess.run(["youtube-dl", "--no-check-certificate", "--get-duration", youtube_link], + stdout=subprocess.PIPE, text=True) +video_length = duration_of_video.stdout +video_length = video_length[:-1] +video_length = time_manipulation(video_length) # video length in seconds + +# Error-2 +if end_time > video_length: + print("ERROR: End time should be less than the Length of video") + quit() + +# removing the channel name from link if it is present +for ch in youtube_link: + if ch == '&': + youtube_link = youtube_link[:youtube_link.index(ch)] + +# getting the download link of the youtube video +download_link = subprocess.run(["youtube-dl", "--no-check-certificate", "-f", "22", "--get-url", youtube_link], + stdout=subprocess.PIPE, text=True) +link = download_link.stdout + +# downloading the video from start_time to end_time +subprocess.run(["ffmpeg", "-ss", str(start_time), "-i", link, "-t", str(duration), "-c:v", "copy", "-c:a", + "copy", Output_file_name]) diff --git a/youtube_downloader/README.md b/youtube_downloader/README.md index 74c7e97b2..fa7f61a8a 100644 --- a/youtube_downloader/README.md +++ b/youtube_downloader/README.md @@ -1,34 +1,34 @@ -# YouTube Downloader - -Basic automation script for download youtube hosted videos. - -## Setup - -For Unix based systems please execute the following command to create venv and install requirements : - -```bash -make init -source .venv/bin/activate -``` - -## Usage - -This script can download YouTube videos in different resolutions, with captions (if available). - -```bash -python ytdownloader.py [OPTIONS] -``` - -```bash -positional arguments: - URL Youtube video URL - -optional arguments: - -h, --help show this help message and exit - -p PATH, --path PATH Destination file path - -c CAPTIONS, --captions CAPTIONS - Captions lang to download (if exists) - -r RES, --res RES Resolution to download (if exists) - -v VERBOSE, --verbose VERBOSE - Show information about script processing -``` +# YouTube Downloader + +Basic automation script for download youtube hosted videos. + +## Setup + +For Unix based systems please execute the following command to create venv and install requirements : + +```bash +make init +source .venv/bin/activate +``` + +## Usage + +This script can download YouTube videos in different resolutions, with captions (if available). + +```bash +python ytdownloader.py [OPTIONS] +``` + +```bash +positional arguments: + URL Youtube video URL + +optional arguments: + -h, --help show this help message and exit + -p PATH, --path PATH Destination file path + -c CAPTIONS, --captions CAPTIONS + Captions lang to download (if exists) + -r RES, --res RES Resolution to download (if exists) + -v VERBOSE, --verbose VERBOSE + Show information about script processing +``` diff --git a/youtube_downloader/makefile b/youtube_downloader/makefile index e78e53c81..7aafa604a 100644 --- a/youtube_downloader/makefile +++ b/youtube_downloader/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/youtube_downloader/requirements.txt b/youtube_downloader/requirements.txt index c7cb42b85..d4c0c1c8d 100644 --- a/youtube_downloader/requirements.txt +++ b/youtube_downloader/requirements.txt @@ -1,3 +1,3 @@ -pkg-resources==0.0.0 -pytube3==9.6.4 -typing-extensions==3.7.4.3 +pkg-resources==0.0.0 +pytube3==9.6.4 +typing-extensions==3.7.4.3 diff --git a/youtube_downloader/ytdownloader.py b/youtube_downloader/ytdownloader.py index 83b0fdbd3..56bf46eb2 100644 --- a/youtube_downloader/ytdownloader.py +++ b/youtube_downloader/ytdownloader.py @@ -1,47 +1,47 @@ -import argparse -from pytube import YouTube - - -def cli_parse(): - cli = argparse.ArgumentParser(prog='ytdownloader', - description='Basic automation script for downloading YouTube hosted videos') - cli.add_argument("url", metavar='URL', type=str, help="Youtube video URL") - cli.add_argument("-p", "--path", type=str, help="Destination file path") - cli.add_argument("-c", "--captions", type=str, - help="Captions lang to download") - cli.add_argument("-r", "--res", type=str, help="Resolution to download") - cli.add_argument("-v", "--verbose", type=bool, default=False, - help="Show information about script processing") - return cli.parse_args() - - -args = cli_parse() -video = YouTube(args.url) -if not args.res: - stream = video.streams.get_highest_resolution() -else: - stream = video.streams.get_by_resolution(args.res) - if not stream: - stream = video.streams.get_highest_resolution() - print( - f"Sorry, '{args.res}' resolution is not available for this video.\nDownloading highest resolution...") - - -if not args.path: - dest = stream.download() -else: - dest = stream.download(args.path) - -if args.captions: - try: - caps = video.captions[args.captions].generate_srt_captions() - filename = f"{dest.split('.', 1)[0]}.srt" - file = open(filename, "w") - file.write(caps) - file.close() - except KeyError: - print( - f"Sorry, '{args.captions}' captions are not available for this video.") - -if args.verbose: - print(f"Successfully downloaded video: {dest}") +import argparse +from pytube import YouTube + + +def cli_parse(): + cli = argparse.ArgumentParser(prog='ytdownloader', + description='Basic automation script for downloading YouTube hosted videos') + cli.add_argument("url", metavar='URL', type=str, help="Youtube video URL") + cli.add_argument("-p", "--path", type=str, help="Destination file path") + cli.add_argument("-c", "--captions", type=str, + help="Captions lang to download") + cli.add_argument("-r", "--res", type=str, help="Resolution to download") + cli.add_argument("-v", "--verbose", type=bool, default=False, + help="Show information about script processing") + return cli.parse_args() + + +args = cli_parse() +video = YouTube(args.url) +if not args.res: + stream = video.streams.get_highest_resolution() +else: + stream = video.streams.get_by_resolution(args.res) + if not stream: + stream = video.streams.get_highest_resolution() + print( + f"Sorry, '{args.res}' resolution is not available for this video.\nDownloading highest resolution...") + + +if not args.path: + dest = stream.download() +else: + dest = stream.download(args.path) + +if args.captions: + try: + caps = video.captions[args.captions].generate_srt_captions() + filename = f"{dest.split('.', 1)[0]}.srt" + file = open(filename, "w") + file.write(caps) + file.close() + except KeyError: + print( + f"Sorry, '{args.captions}' captions are not available for this video.") + +if args.verbose: + print(f"Successfully downloaded video: {dest}") diff --git a/zip_extractor/README.md b/zip_extractor/README.md index c08d6cd1e..128596586 100644 --- a/zip_extractor/README.md +++ b/zip_extractor/README.md @@ -1,25 +1,25 @@ -# Zip Extractor - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - - 1. Download the code - 2. Setup and activate virtual environment - 3. Run the code with python - - *Download Python from: https://python.org/downloads/* - Make sure that python is added to path in your environment variables. - After this, open command prompt in the folder where you extracted the code. - Type `make init` and press enter. - Then run the code and follow the prompts. - - - *Caution*: Currently I am using Python 3.7 version in my machine, so the library named zipfile is installed - using command "pip install zipfile37". Here 37 refers to the version. If your python version is other than - 3.7, then I would recommend you to check the version and type the respective number there. - - **Thank you** +# Zip Extractor + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + + 1. Download the code + 2. Setup and activate virtual environment + 3. Run the code with python + + *Download Python from: https://python.org/downloads/* + Make sure that python is added to path in your environment variables. + After this, open command prompt in the folder where you extracted the code. + Type `make init` and press enter. + Then run the code and follow the prompts. + + + *Caution*: Currently I am using Python 3.7 version in my machine, so the library named zipfile is installed + using command "pip install zipfile37". Here 37 refers to the version. If your python version is other than + 3.7, then I would recommend you to check the version and type the respective number there. + + **Thank you** diff --git a/zip_extractor/makefile b/zip_extractor/makefile index e78e53c81..7aafa604a 100644 --- a/zip_extractor/makefile +++ b/zip_extractor/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/zip_extractor/requirements.txt b/zip_extractor/requirements.txt index 7ee968908..c41162224 100644 --- a/zip_extractor/requirements.txt +++ b/zip_extractor/requirements.txt @@ -1,2 +1,2 @@ -zipfile37 == 0.1.3 -easygui >= 0.98.1 +zipfile37 == 0.1.3 +easygui >= 0.98.1 diff --git a/zip_extractor/zip_extractor.py b/zip_extractor/zip_extractor.py index fd0accad1..6ab2c102a 100644 --- a/zip_extractor/zip_extractor.py +++ b/zip_extractor/zip_extractor.py @@ -1,28 +1,28 @@ -from zipfile import ZipFile -import easygui -import time -# import the required libraries -print("Select the path of zip file...") -# a function in easygui that opens -# a window for selecrting the zip file -path = easygui.fileopenbox() -# for better presentation -# i added a break -time.sleep(2) - -# opening the zip file selected -# in read mode -with ZipFile(path, 'r') as zip: - # prints the contents in the zip folder - zip.printdir() - print("Select the destination directory to extract!!") - # prompts the user to select the destination - # folder where zip will be extracted - path1 = easygui.diropenbox() - print("Extracting files to the selected directory...") - time.sleep(3) - # extracts all the contents in the selected path - zip.extractall(path1) - time.sleep(2) - # prints a message after extracting - print("Done!") +from zipfile import ZipFile +import easygui +import time +# import the required libraries +print("Select the path of zip file...") +# a function in easygui that opens +# a window for selecrting the zip file +path = easygui.fileopenbox() +# for better presentation +# i added a break +time.sleep(2) + +# opening the zip file selected +# in read mode +with ZipFile(path, 'r') as zip: + # prints the contents in the zip folder + zip.printdir() + print("Select the destination directory to extract!!") + # prompts the user to select the destination + # folder where zip will be extracted + path1 = easygui.diropenbox() + print("Extracting files to the selected directory...") + time.sleep(3) + # extracts all the contents in the selected path + zip.extractall(path1) + time.sleep(2) + # prints a message after extracting + print("Done!") diff --git a/zip_password_cracker/README.md b/zip_password_cracker/README.md index d603139f0..e426a40b8 100644 --- a/zip_password_cracker/README.md +++ b/zip_password_cracker/README.md @@ -1,20 +1,20 @@ -# Zip Password Cracker - -## Setup and activate virtual environment : -For Unix based systems please execute the following command to create venv and install requirements. -``` -make init -source .venv/bin/activate -``` - -Attempts to brute force the password of a zip file. -How to user: -``` -python3 zip_password_cracker.py --zip --passwords -``` -If no dictionary file is passed, it will use the passwords.txt file instead. - -password.txt Sources: https://github.com/danielmiessler/SecLists/ -Got from there file with 10k most common credentials. - -**You will get passwords.txt file [here](https://gist.github.com/pawangeek/c96476f5d7e874e888748ef73cd1a6f7)** +# Zip Password Cracker + +## Setup and activate virtual environment : +For Unix based systems please execute the following command to create venv and install requirements. +``` +make init +source .venv/bin/activate +``` + +Attempts to brute force the password of a zip file. +How to user: +``` +python3 zip_password_cracker.py --zip --passwords +``` +If no dictionary file is passed, it will use the passwords.txt file instead. + +password.txt Sources: https://github.com/danielmiessler/SecLists/ +Got from there file with 10k most common credentials. + +**You will get passwords.txt file [here](https://gist.github.com/pawangeek/c96476f5d7e874e888748ef73cd1a6f7)** diff --git a/zip_password_cracker/makefile b/zip_password_cracker/makefile index e78e53c81..7aafa604a 100644 --- a/zip_password_cracker/makefile +++ b/zip_password_cracker/makefile @@ -1,9 +1,9 @@ -VENV ?= .venv -REQUIREMENTS_FILE ?= requirements.txt - -init: - python3 -m venv $(VENV) - $(VENV)/bin/python -m pip install --upgrade pip - if [ -f $(REQUIREMENTS_FILE) ]; \ - then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ +VENV ?= .venv +REQUIREMENTS_FILE ?= requirements.txt + +init: + python3 -m venv $(VENV) + $(VENV)/bin/python -m pip install --upgrade pip + if [ -f $(REQUIREMENTS_FILE) ]; \ + then $(VENV)/bin/python -m pip install -r $(REQUIREMENTS_FILE); \ fi \ No newline at end of file diff --git a/zip_password_cracker/zip_password_cracker.py b/zip_password_cracker/zip_password_cracker.py index d882e3221..a1f1448b0 100644 --- a/zip_password_cracker/zip_password_cracker.py +++ b/zip_password_cracker/zip_password_cracker.py @@ -1,35 +1,35 @@ -#!/usr/bin/python -from pathlib import Path -from zipfile import ZipFile - -import click - - -def extract_zip(zip_file: ZipFile, password_file: Path): - with open(password_file, 'r') as passwords: - for password in passwords.readlines(): - try: - zip_file.extractall(pwd=password.strip().encode()) - print(f"Found password: {password}") - break - except RuntimeError: - pass - else: - print("Password not found") - - -@click.command(context_settings={'help_option_names': ['-h', '--help']}) -@click.option('--zip', help='Set path to zip file') -@click.option( - '--passwords', - default=Path().cwd() / 'passwords.txt', - help='Set path to file with passwords', -) -def main(zip, passwords): - """Simple program that greets NAME for a total of COUNT times.""" - zip_file = ZipFile(zip) - extract_zip(zip_file, passwords) - - -if __name__ == '__main__': - main() +#!/usr/bin/python +from pathlib import Path +from zipfile import ZipFile + +import click + + +def extract_zip(zip_file: ZipFile, password_file: Path): + with open(password_file, 'r') as passwords: + for password in passwords.readlines(): + try: + zip_file.extractall(pwd=password.strip().encode()) + print(f"Found password: {password}") + break + except RuntimeError: + pass + else: + print("Password not found") + + +@click.command(context_settings={'help_option_names': ['-h', '--help']}) +@click.option('--zip', help='Set path to zip file') +@click.option( + '--passwords', + default=Path().cwd() / 'passwords.txt', + help='Set path to file with passwords', +) +def main(zip, passwords): + """Simple program that greets NAME for a total of COUNT times.""" + zip_file = ZipFile(zip) + extract_zip(zip_file, passwords) + + +if __name__ == '__main__': + main()