import logging
import re
import time
from json import loads as json_parse
from os import walk as walkdir

from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required
from django.core.exceptions import ValidationError
from django.core.paginator import Paginator
from django.core.validators import validate_email
from django.db.models import Count, Q, Subquery
from django.http import Http404, JsonResponse
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.templatetags.static import static
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt

from app.utils import get_default_network, get_profiles_from_text
from cacheops import cached_as, cached_view, cached_view_as
from dashboard.models import Activity, Bounty, HackathonEvent, Profile, get_my_earnings_counter_profiles, get_my_grants
from dashboard.notifications import amount_usdt_open_work, open_bounties
from dashboard.tasks import grant_update_email_task
from economy.models import Token
from marketing.mails import mention_email, new_funding_limit_increase_request, new_token_request, wall_post_email
from marketing.models import Alumni, Job, LeaderboardRank
from marketing.utils import get_or_save_email_subscriber, invite_to_slack
from perftools.models import JSONStore
from ratelimit.decorators import ratelimit
from retail.emails import render_nth_day_email_campaign
from retail.helpers import get_ip
from townsquare.tasks import increment_view_counts

from .forms import FundingLimitIncreaseRequestForm
from .utils import programming_languages

logger = logging.getLogger(__name__)

connect_types = ['status_update', 'wall_post', 'new_bounty', 'created_quest', 'new_grant', 'created_kudos', 'consolidated_leaderboard_rank', 'consolidated_mini_clr_payout']

def get_activities(tech_stack=None, num_activities=15):
    # get activity feed

    activities = Activity.objects.select_related('bounty').filter(bounty__network='mainnet').order_by('-created')
    if tech_stack:
        activities = activities.filter(bounty__metadata__icontains=tech_stack)
    activities = activities[0:num_activities]
    return activities

def index(request):

    products = [
        {
            'group' : 'grow_oss',
            'products': [
                {
                    'img': static('v2/images/home/bounties.svg'),
                    'name': 'BOUNTIES',
                    'description': 'Get paid for solving open source bounties.',
                    'link': '/bounties/funder'
                }
            ]
        },
        {
            'group' : 'maintain_oss',
            'products': [
                {
                    'img': static('v2/images/home/codefund.svg'),
                    'name': 'CODEFUND',
                    'description': 'Ethical advertising for open source.',
                    'link': 'https://codefund.app'
                },
                {
                    'img': static('v2/images/home/grants.svg'),
                    'name': 'GRANTS',
                    'description': 'Sustainable funding for open source.',
                    'link': '/grants'
                }
            ]
        },
        {
            'group' : 'build_oss',
            'products': [
                {
                    'img': static('v2/images/home/kudos.svg'),
                    'name': 'KUDOS',
                    'description': 'A new way to show appreciation.',
                    'link': '/kudos'
                }
            ]
        }
    ]

    know_us = [
        {
            'text': 'Our Vision',
            'link': '/vision'
        },
        {
            'text': 'Our Products',
            'link': '/products'
        },
        {
            'text': 'Our Team',
            'link': '/about#team'
        },
        {
            'text': 'Our Results',
            'link': '/results'
        },
        {
            'text': 'Our Values',
            'link': '/mission'
        },
        {
            'text': 'Our Token',
            'link': '/not_a_token'
        }
    ]

    press = [
        {
            'link': 'https://twit.tv/shows/floss-weekly/episodes/474',
            'img' : 'v2/images/press/floss_weekly.jpg'
        },
        {
            'link': 'https://epicenter.tv/episode/257/',
            'img' : 'v2/images/press/epicenter.jpg'
        },
        {
            'link': 'http://www.ibtimes.com/how-web-30-will-protect-our-online-identity-2667000',
            'img': 'v2/images/press/ibtimes.jpg'
        },
        {
            'link': 'https://www.forbes.com/sites/jeffersonnunn/2019/01/21/bitcoin-autonomous-employment-workers-wanted/',
            'img': 'v2/images/press/forbes.jpg'
        },
        {
            'link': 'https://unhashed.com/cryptocurrency-news/gitcoin-introduces-collectible-kudos-rewards/',
            'img': 'v2/images/press/unhashed.jpg'
        },
        {
            'link': 'https://www.coindesk.com/meet-dapp-market-twist-open-source-winning-developers/',
            'img': 'v2/images/press/coindesk.png'
        },
        {
            'link': 'https://softwareengineeringdaily.com/2018/04/03/gitcoin-open-source-bounties-with-kevin-owocki/',
            'img': 'v2/images/press/se_daily.png'
        },
        {
            'link': 'https://www.ethnews.com/gitcoin-offers-bounties-for-ens-integration-into-dapps',
            'img': 'v2/images/press/ethnews.jpg'
        },
        {
            'link': 'https://www.hostingadvice.com/blog/grow-open-source-projects-with-gitcoin/',
            'img': 'v2/images/press/hosting-advice.png'
        }
    ]

    articles = [
        {
            'link': 'https://medium.com/gitcoin/progressive-elaboration-of-scope-on-gitcoin-3167742312b0',
            'img': static("v2/images/medium/1.png"),
            'title': _('Progressive Elaboration of Scope on Gitcoin'),
            'description': _('What is it? Why does it matter? How can you deal with it on Gitcoin?'),
            'alt': 'gitcoin scope'
        },
        {
            'link': 'https://gitcoin.co/blog/commit-reveal-scheme-on-ethereum/',
            'img': static("v2/images/medium/2.png"),
            'title': _('Commit Reveal Scheme on Ethereum'),
            'description': _('Hiding Actions and Generating Random Numbers'),
            'alt': 'commit reveal scheme'
        },
        {
            'link': 'https://medium.com/gitcoin/announcing-open-kudos-e437450f7802',
            'img': static("v2/images/medium/3.png"),
            'title': _('Announcing Open Kudos'),
            'description': _('Our vision for integrating Kudos in any (d)App'),
            'alt': 'open kudos'
        }
    ]

    context = {
        'products': products,
        'know_us': know_us,
        'press': press,
        'articles': articles,
        'hide_newsletter_caption': True,
        'hide_newsletter_consent': True,
        'newsletter_headline': _("Get the Latest Gitcoin News! Join Our Newsletter."),
        'title': _('Grow Open Source: Get crowdfunding and find freelance developers for your software projects, paid in crypto')
    }
    return TemplateResponse(request, 'home/index.html', context)

def funder_bounties_redirect(request):
    return redirect(funder_bounties)

def funder_bounties(request):

    onboard_slides = [
        {
            'img': static("v2/images/presskit/illustrations/prime.svg"),
            'title': _('Are you a developer or designer?'),
            'subtitle': _('Contribute to exciting OSS project and get paid!'),
            'type': 'contributor',
            'active': 'active',
            'more': '/bounties/contributor'
        },
        {
            'img': static("v2/images/presskit/illustrations/regulus-white.svg"),
            'title': _('Are you a funder or project organizer?'),
            'subtitle': _('Fund your OSS bounties and get work done!'),
            'type': 'funder',
            'more': '/how/funder'
        }
    ]

    slides = [
        ("Dan Finlay", static("v2/images/testimonials/dan.jpg"),
         _("Once we had merged in multiple language support from a bounty, it unblocked the \
         path to all other translations, and what better way to get lots of dif erent \
         translations than with bounties from our community? A single tweet of publicity \
         and we had something like 20 language requests, and 10 language pull requests. It’s been total magic."),
         'https://github.com/danfinlay', "Metamask -- Internationalization"),
        ("Phil Elsasser", static("v2/images/testimonials/phil.jpg"),
         _("By design or not, there is an element of trust inherent within Gitcoin. This isn’t \
         the bad kind of “trust” that we are all trying to move away from in a centralized world, \
         but a much better sense of community trust that gets established through the bounty process."),
         'http://www.marketprotocol.io/', 'Market'),
        ("John Maurelian", static("v2/images/testimonials/maurelian.jpg"),
         _("Gitcoin helps us to finally close out the issues we've been meaning to get around to for too long"),
         "https://consensys.github.io/smart-contract-best-practices/", 'Consensys Diligence -- Documentation Bounties'),
        ("Kames CG", static("v2/images/testimonials/kames.jpg"),
         _("uPort is still in the process of Open Sourcing all of our code, so Gitcoin at the present moment, \
         helps uPort plant seeds within the growing Ethereum developer community, that we expect will blossom \
         into flourishing opportunities in the future. Put simply, as opposed to running marketing campaign, \
         we can use bounties to stay present in front of potential developers we want to engage with."),
         'https://github.com/KamesCG', 'Uport'),
        ("Piper", static("v2/images/testimonials/pipermerriam.jpg"),
         _("Although we’ve only hired two developers, there is no doubt that we could have sourced more. \
         Gitcoin has been the strongest hiring signal in all of the hiring I’ve ever done."),
         'https://github.com/pipermerriam', 'Pipermerriam'),
        ("Joseph Schiarizzi", static("v2/images/testimonials/jschiarizzi.jpeg"),
         _("On a Friday I needed a front end done for a project due in 48 hours.  When everyone I knew was busy, \
         gitcoiners were able to help me make my deadline, with fast, affordable, & high quality work."),
         'https://github.com/jschiarizzi', 'Fourth Wave')
    ]

    gitcoin_description = _(
        "A community at the intersection of blockchain and open source. A place for developers to collaborate in a new system, where open source money builds in monetization for open source repositories."
    )

    context = {
        'onboard_slides': onboard_slides,
        'activities': get_activities(),
        'is_outside': True,
        'slides': slides,
        'slideDurationInMs': 6000,
        'active': 'bounties_funder',
        'hide_newsletter_caption': True,
        'hide_newsletter_consent': True,
        'gitcoin_description': gitcoin_description,
        'newsletter_headline': _("Get the Latest Gitcoin News! Join Our Newsletter."),
        'meta_title': "Grow Open Source: Find Freelance Developers & Open Source Bug Bounties - Gitcoin",
        'meta_description': "The Gitcoin platform connects freelance developers with open bug bounties or online jobs, paid in crypto (ETH). Leverage a global workforce to quickly complete software development and coding jobs."
    }
    return TemplateResponse(request, 'bounties/funder.html', context)

def contributor_bounties_redirect(request, tech_stack):
    return redirect(contributor_bounties, tech_stack= '/'+ tech_stack)

def contributor_bounties(request, tech_stack):

    onboard_slides = [
        {
            'img': static("v2/images/presskit/illustrations/regulus-white.svg"),
            'title': _('Are you a funder or project organizer?'),
            'subtitle': _('Fund your OSS bounties and get work done!'),
            'type': 'funder',
            'active': 'active',
            'more': '/bounties/funder'
        },
        {
            'img': static("v2/images/presskit/illustrations/prime.svg"),
            'title': _('Are you a developer or designer?'),
            'subtitle': _('Contribute to exciting OSS project and get paid!'),
            'type': 'contributor',
            'more': '/how/contributor'
        }
    ]

    slides = [
        ("Daniel", static("v2/images/testimonials/gitcoiners/daniel.jpeg"),
         _("When I found Gitcoin I was gladly surprised that it took one thing and did it well. \
         It took the Ethereum tech and used it as a bridge to technology with open source Jobs.  \
         Even though Gitcoin is still in it’s early stages, I think it’s filled with potential to grow."),
         'https://github.com/dmerrill6'),
        ("CryptoMental", static("v2/images/testimonials/gitcoiners/cryptomental.png"),
         _(" think the great thing about GitCoin is how easy it is for projects to reach out to worldwide talent. \
         GitCoin helps to find people who have time to contribute and increase speed of project development. \
         Thanks to GitCoin a bunch of interesting OpenSource projects got my attention!"),
         'https://github.com/cryptomental'),
        ("Elan", static("v2/images/testimonials/gitcoiners/elan.jpeg"),
         _("The bounty process with Gitcoin is pretty amazing.  Just go on the website, find an issue you can \
         work on, you claim it.  All you do then is submit your code to Github, get the code merged.  \
         Once it’s merged, the smart contract kicks in and sends the money to your Ethereum account.  \
         The whole process is pretty smooth.  There’s a giant slack community.  It puts the freelance \
         market back in the hands of the community!"),
         "https://github.com/elaniobro"),
        ("Jack", static("v2/images/testimonials/gitcoiners/jack.jpeg"),
         _("I really like Gitcoin because it’s allowed me to get involved in some really interesting \
         Open Source Projects.  I’ve written code for MyEtherWallet and Gitcoin itself.  \
         I think Gitcoin is becoming a great asset for the Ethereum ecosystem."),
         'https://github.com/jclancy93'),
        ("Miguel Angel Rodriguez Bermudez", static("v2/images/testimonials/gitcoiners/miguel.jpeg"),
         _("I came across Gitcoin 3 months ago.  I was hearing lots of ideas about projects involving \
         cryptocurrencies, and I kept thinking \"what about open source projects?\".  I see Gitcoin as \
         the next level of freelance, where you can not only help repos on Github, but get money out of \
         it.  It is that simple and it works."),
         'https://github.com/marbrb'),
        ("Octavio Amuchástegui", static("v2/images/testimonials/gitcoiners/octavioamu.jpeg"),
         _("I'm in love with Gitcoin. It isn't only a platform, it's a community that gives me the \
         opportunity to open my network and work with amazing top technology projects and earn some \
         money in a way I'm visible to the dev community and work opportunities. Open source is amazing, \
         and is even better to make a living from it, I think is the future of development."),
         'https://github.com/octavioamu')
    ]

    gitcoin_description = _(
        "A community for developers to collaborate and monetize their skills while working \
        on Open Source projects through bounties."
    )

    projects = [
        {
            'name': 'Augur Logo',
            'source': 'v2/images/project_logos/augur.png'
        },
        {
            'name': 'Bounties Logo',
            'source': 'v2/images/project_logos/bounties.png'
        },
        {
            'name': 'Balance Logo',
            'source': 'v2/images/project_logos/balance.png'
        },
        {
            'name': 'Metamask Logo',
            'source': 'v2/images/project_logos/metamask.png'
        },
        {
            'name': 'uPort Logo',
            'source': 'v2/images/project_logos/uport.png'
        },
        {
            'name': 'Market Protocol Logo',
            'source': 'v2/images/project_logos/market.png'
        },
        {
            'name': 'Trust Wallet Logo',
            'source': 'v2/images/project_logos/trust.png'
        },
        {
            'name': 'MCrypto Logo',
            'source': 'v2/images/project_logos/mycrypto.png'
        },
        {
            'name': 'Truffle Logo',
            'source': 'v2/images/project_logos/truffle.png'
        },
        {
            'name': 'Solidity Logo',
            'source': 'v2/images/project_logos/solidity.png'
        },
        {
            'name': 'Casper Logo',
            'source': 'v2/images/project_logos/casper.png'
        },
        {
            'name': 'Wyvern Logo',
            'source': 'v2/images/project_logos/wyvern.png'
        },
        {
            'name': 'Ethereum Logo',
            'source': 'v2/images/project_logos/eth.png'
        },
        {
            'name': 'Livepeer Logo',
            'source': 'v2/images/project_logos/livepeer.png'
        },
        {
            'name': 'Raiden Logo',
            'source': 'v2/images/project_logos/raiden.png'
        },
        {
            'name': 'Databroker Logo',
            'source': 'v2/images/project_logos/databroker.png'
        }
    ]

    # tech_stack = '' #uncomment this if you wish to disable contributor specific LPs
    context = {
        'onboard_slides': onboard_slides,
        'slides': slides,
        'slideDurationInMs': 6000,
        'active': 'bounties_coder',
        'newsletter_headline': _("Be the first to find out about newly posted freelance jobs."),
        'hide_newsletter_caption': True,
        'hide_newsletter_consent': True,
        'gitcoin_description': gitcoin_description,
        'projects': projects,
        'contributor_list': [
            { 'link': "/python", 'text': "Python"},
            { 'link': "/javascript", 'text': "JavaScript"},
            { 'link': "/rust", 'text': "Rust"},
            { 'link': "/solidity", 'text': "Solidity"},
            { 'link': "/design", 'text': "Design"},
            { 'link': "/html", 'text': "HTML"},
            { 'link': "/ruby", 'text': "Ruby"},
            { 'link': "/css", 'text': "CSS"},
        ]
    }

    if tech_stack == 'new':
        return redirect('new_funding_short')

    try:
        new_context = JSONStore.objects.get(view='contributor_landing_page', key=tech_stack).data

        for key, value in new_context.items():
            context[key] = value
    except Exception as e:
        logger.exception(e)
        raise Http404

    return TemplateResponse(request, 'bounties/contributor.html', context)

def get_contributor_landing_page_context(tech_stack):
    available_bounties_count = open_bounties().count()
    available_bounties_worth = amount_usdt_open_work()
    activities = get_activities(tech_stack)
    return {
        'activities': activities,
        'title': tech_stack.title() + str(_(" Open Source Opportunities")) if tech_stack else str(_("Open Source Opportunities")),
        'available_bounties_count': available_bounties_count,
        'available_bounties_worth': available_bounties_worth,
        'tech_stack': tech_stack,

    }

def how_it_works(request, work_type):
    """Show How it Works / Funder page."""
    if work_type not in ['funder', 'contributor']:
        raise Http404
    if work_type == 'contributor':
        title = _('How to Find & Complete Open Bounties | Gitcoin')
        desc = _('Learn how to get paid for open bug bounties and get paid in crypto (ETH or any ERC-20 token)')
    elif work_type == 'funder':
        title = _('How to Create & Fund Issues/Bounties | Gitcoin')
        desc = _('Learn how to create open bug bounties and get freelance developers to complete your job/task.')
    context = {
        'active': f'how_it_works_{work_type}',
        'title': title,
        'desc': desc
    }
    return TemplateResponse(request, 'how_it_works/index.html', context)

def robotstxt(request):
    hidden_profiles = list(JSONStore.objects.get(view='hidden_profiles').data)
    context = {
        'settings': settings,
        'hidden_profiles': hidden_profiles,
    }
    return TemplateResponse(request, 'robots.txt', context, content_type='text')

def about(request):
    core_team = [
        (
            "Kevin Owocki",
            "All the things",
            "owocki",
            "owocki",
            "The Community",
            "Avocado Toast",
            "kevin",
            "Summoner of Bots",
            "owocki",
            True
        ),
        (
            "Joe Lubin",
            "Consensys",
            "",
            "",
            "Meshiness",
            "",
            "joe",
            "Harbringer of Decentralization",
            "ethereumJoseph",
            True
        ),
        (
            "Alisa March",
            "User Experience Design",
            "PixelantDesign",
            "pixelant",
            "Tips",
            "Apple Cider Doughnuts",
            "alisa",
            "Pixel Mage",
            "pixelant",
            True
        ),
        (
            "Eric Berry",
            "OSS Funding",
            "coderberry",
            "ericberry",
            "Chrome/Firefox Extension",
            "Pastel de nata",
            "eric",
            "Burnout Healer",
            "coderberry",
            True
        ),
        (
            "Vivek Singh",
            "Community Buidl-er",
            "vs77bb",
            "vivek-singh-b5a4b675",
            "Gitcoin Requests",
            "Tangerine Gelato",
            "vivek",
            "Campfire StoryTeller",
            "vsinghdothings",
            True
        ),
        (
            "Aditya Anand M C",
            "Engineering",
            "thelostone-mc",
            "aditya-anand-m-c-95855b65",
            "The Community",
            "Cocktail Samosa",
            "aditya",
            "Block Welder",
            "thelostone_mc",
            True
        ),
        (
            "Scott Moore",
            "Biz Dev",
            "ceresstation",
            "scott-moore-a2970075",
            "Issue Explorer",
            "Teriyaki Chicken",
            "scott",
            "Phase Shifter",
            "notscottmoore",
            True
        ),
        (
            "Octavio Amuchástegui",
            "Front End Dev",
            "octavioamu",
            "octavioamu",
            "The Community",
            "Homemade italian pasta",
            "octavio",
            "Bugs Breeder",
            "octavioamu",
            True
        ),
        (
            "Frank Chen",
            "Data & Product",
            "frankchen07",
            "frankchen07",
            "Kudos!",
            "Crispy pork belly",
            "frank",
            "Hashed Scout",
            "",
            True
        ),
        (
            "Nate Hopkins",
            "Engineering",
            "hopsoft",
            None,
            "Bounties",
            "Chicken tikka masala",
            "nate",
            "Lord of Night's Watch",
            "hopsoft",
            True
        ),
        (
            "Alessandro Voto",
            "DevRel",
            "alexvotofuture",
            None,
            "Devvies",
            "Tacos",
            "alex",
            "Starship Captain",
            "avotofuture",
            True
        ),
        (
            "Dan Lipert",
            "Engineering",
            "danlipert",
            "danlipert",
            "EIP 1337",
            "Tantan Ramen",
            "dan",
            "Blockchain Artificer",
            "dan_lipert",
            True
        ),
        (
            "Connor O'Day",
            "DevRel",
            "connoroday",
            "connoroday",
            "the lols",
            "Robertas Pizza",
            "connor",
            "Druid of The Chain",
            "connoroday0",
            True
        ),
        (
            "Joseph Chen",
            "Operations",
            "josephchen",
            "josephchen",
            "Ethical Ads",
            "DIY",
            "joseph",
            "Arithmagician",
            "",
            True
        ),
        (
            "gitcoinbot",
            "beep boop bop",
            "gitcoinbot",
            "gitcoinbot",
            "everything that's automated",
            "bits",
            "gitcoinbot",
            "Loveable Companion",
            "",
            False
        )

    ]
    exclude_community = ['kziemiane', 'owocki', 'mbeacom']
    community_members = [
    ]
    leadeboardranks = LeaderboardRank.objects.filter(active=True, product='all', leaderboard='quarterly_earners').exclude(github_username__in=exclude_community).order_by('-amount').cache()[0: 15]
    for lr in leadeboardranks:
        package = (lr.avatar_url, lr.github_username, lr.github_username, '')
        community_members.append(package)

    alumnis = [
    ]
    for alumni in Alumni.objects.select_related('profile').filter(public=True).exclude(organization='gitcoinco').cache():
        package = (alumni.profile.avatar_url, alumni.profile.username, alumni.profile.username, alumni.organization)
        alumnis.append(package)

    context = {
        'core_team': core_team,
        'community_members': community_members,
        'alumni': alumnis,
        'total_alumnis': str(Alumni.objects.count()),
        'active': 'about',
        'title': 'About',
        'is_outside': True,
    }
    return TemplateResponse(request, 'about.html', context)

def mission(request):
    """Render the Mission response."""

    values = [
        {
            'name': _('Self Reliance'),
            'img': 'v2/images/mission/value/collaborative.svg',
            'alt': 'we-collobarate-icon'
        },
        {
            'name': _('Intellectual honesty'),
            'img': 'v2/images/mission/value/love_hands.svg',
            'alt': 'intellectual-honesty-icon'
        },
        {
            'name': _('Collaboration'),
            'img': 'v2/images/mission/value/humble.svg',
            'alt': 'humble-icon'
        },
        {
            'name': _('Empathy'),
            'img': 'v2/images/mission/value/empathetic.svg',
            'alt': 'empathy-icon'
        },
        {
            'name': _('Stress Reducers'),
            'img': 'v2/images/mission/value/stress_reducing.svg',
            'alt': 'stress-reduce-icon'
        },
        {
            'name': _('Inclusivity'),
            'img': 'v2/images/mission/value/inclusive.svg',
            'alt': 'inclusive-icon'
        },
        {
            'name': _('Giving first'),
            'img': 'v2/images/mission/value/give_first.svg',
            'alt': 'give-first-icon'
        }
    ]

    interactions = [
        {
            'text': _('We happen to the world. We don\'t let the world happen to us.'),
            'img': 'v2/images/mission/interact/world.svg',
            'alt': 'world-icon'
        },
        {
            'text': _('We show, don\'t tell.'),
            'img': 'v2/images/mission/interact/book.svg',
            'alt': 'openness-icon'
        },
        {
            'text': _('We are thoughtful, clear, and direct.'),
            'img': 'v2/images/mission/interact/head.svg',
            'alt': 'thoughtful-icon'
        },
        {
            'text': _('We seek balance.'),
            'img': 'v2/images/mission/interact/scale.svg',
            'alt': 'balance-icon'
        },
        {
            'text': _('We challenge the status quo & are willing to be challenged.'),
            'img': 'v2/images/mission/interact/goal.svg',
            'alt': 'goal-icon'
        },
        {
            'text': _('We fix things twice.'),
            'img': 'v2/images/mission/interact/hammer.svg',
            'alt': 'fix-twicw-icon'
        },
        {
            'text': _('We identify and validate our assumptions.'),
            'img': 'v2/images/mission/interact/microscope.svg',
            'alt': 'microscope-icon'
        },
        {
            'text': _('We care about people (not just tasks).'),
            'img': 'v2/images/mission/interact/people_care.svg',
            'alt': 'care-icon'
        },
        {
            'text': _('We listen.'),
            'img': 'v2/images/mission/interact/hear.svg',
            'alt': 'microscope-icon'
        },
        {
            'text': _('We value pragmatism over dogmatism.'),
            'img': 'v2/images/mission/interact/swiss_army.svg',
            'alt': 'pargma-icon'
        }
    ]

    context = {
        'is_outside': True,
        'active': 'mission',
        'title': 'Mission',
        'card_title': _('Gitcoin is a mission-driven organization.'),
        'card_desc': _('Our mission is to grow open source.'),
        'avatar_url': static('v2/images/grow_open_source.png'),
        'values': values,
        'interactions': interactions
    }
    return TemplateResponse(request, 'mission.html', context)

def jobs(request):
    job_listings = Job.objects.filter(active=True)
    context = {
        'active': 'jobs',
        'title': 'Jobs',
        'job_listings': job_listings
    }
    return TemplateResponse(request, 'jobs.html', context)

def vision(request):
    """Render the Vision response."""
    videoLinks = [
        'https://www.youtube.com/embed/wo0KkSH-6eg',
        'https://www.youtube.com/embed/nZTVMEh9k5U',
        'https://www.youtube.com/embed/F2yeOFlRE0E'
    ]
    context = {
        'is_outside': True,
        'active': 'vision',
        'avatar_url': static('v2/images/vision/triangle.jpg'),
        'title': 'Vision',
        'videoLinks': videoLinks,
        'card_title': _("Gitcoin's Vision for a Web3 World"),
        'card_desc': _("Gitcoin's Vision for a web3 world is to make it easy for developers to find paid work in open source."),
    }
    return TemplateResponse(request, 'vision.html', context)

def avatar(request):
    """Render the avatar response."""
    from avatar.models import AvatarTheme

    default_back = get_leaderboard_back(request)
    back = request.GET.get('back', default_back[1])
    img = request.GET.get('img', default_back[0])

    context = {
        'is_outside': True,
        'active': 'avatar',
        'title': 'Avatar Builder',
        'card_title': _("Free Avatar Builder"),
        'card_desc': _('Gitcoin\'s Free Avatar Creator is an online tool to build a character for yourself.  It has dozens of options to show off your bad-self.  No strings attached, Always free.'),
        'avatar_url': "https://c.gitcoin.co/avatars/d1a33d2bcb7bbfef50368bca73111fae/fryggr.png",
        'back': back,
        'img': img,
        'avatar_options': AvatarTheme.objects.filter(active=True).order_by('-popularity'),
    }
    return TemplateResponse(request, 'avatar_landing.html', context)

def get_leaderboard_back(request):
    default_back_safe = [['s10.png', i] for i in range(24, 33)]
    default_back_crazy = [['s9.png', 3], ['s10.png', 10], ['s10.png', 25], ['s10.png', 33], ['s10.png', 4], ['s10.png', 8], ['s9.png', 14]]
    default_back = default_back_safe

    default_back_i = int(request.GET.get('i', int(timezone.now().strftime("%j")))) % len(default_back)
    default_back = default_back[default_back_i]
    return default_back

def products(request):
    """Render the Products response."""
    products = [
        {
            'name': 'Town Square',
            'heading': _("A Web3-enabled social networking bazaar."),
            'description': _("Gitcoin offers social features that uses mechanism design create a community that #GivesFirst."),
            'link': 'https://gitcoin.co/townsquare',
            'img': static('v2/images/products/social.png'),
            'logo': static('v2/images/helmet.svg'),
            'service_level': '',
            'traction': '100s of posts per day',
        },
        {
            'name': 'Chat',
            'heading': _("Reach your favorite Gitcoiner's in realtime.."),
            'description': _("Gitcoin Chat is an enterprise-grade solution to connect with your favorite Gitcoiners in realtime.  Download the mobile apps to stay connected on the go!"),
            'link': 'https://gitcoin.co/chat/landing',
            'img': static('v2/images/products/chat.png'),
            'logo': static('v2/images/helmet.svg'),
            'service_level': '',
            'traction': '100s of DAUs',
        },
        {
            'name': 'hackathons',
            'heading': _("Hack with the best companies in web3."),
            'description': _("Gitcoin offers Virtual Hackathons about once a month; Earn Prizes by working with some of the best projects in the decentralization space."),
            'link': 'https://hackathons.gitcoin.co',
            'img': static('v2/images/products/graphics-hackathons.png'),
            'logo': static('v2/images/products/hackathons-logo.svg'),
            'service_level': 'Full Service',
            'traction': '1-3 hacks/month worth $40k/mo',
        },
        {
            'name': 'grants',
            'heading': _("Sustainable funding for open source"),
            'description': _("Gitcoin Grants are a fast, easy & secure way to provide recurring token \
                            contributions to your favorite OSS maintainers. Plus, with our NEW quarterly $100k+ matching funds it's now even easier to fund your OSS work! "),
            'link': '/grants',
            'img': static('v2/images/products/graphics-Grants.png'),
            'logo': static('v2/images/products/grants-logo.svg'),
            'service_level': 'Self Service',
            'traction': 'over $1mm in GMV',
        },
        {
            'name': 'kudos',
            'heading': _("Show your appreciation with collectible tokens"),
            'description': _("Kudos is a way of showing your appreciation to another Gitcoin member.\
                            It's also a way to showcase special skills that a member might have."),
            'link': '/kudos',
            'img': static('v2/images/products/graphics-Kudos.png'),
            'logo': static('v2/images/products/kudos-logo.svg'),
            'service_level': 'Self Service',
            'traction': '1200+ kudos sent/month',
        },
        {
            'name': 'bounties',
            'heading': _("Solve bounties. Get paid. Contribute to open source"),
            'description': _("Collaborate and monetize your skills while working on Open Source projects \
                            through bounties."),
            'link': '/explorer',
            'img': static('v2/images/products/graphics-Bounties.png'),
            'logo': static('v2/images/products/gitcoin-logo.svg'),
            'service_level': 'Self Service',
            'traction': '$25k/mo',
        },
        {
            'name': 'codefund',
            'heading': _("Ethical advertising for developers"),
            'description': _("CodeFund is an open source ad platform that funds contributors of the open \
                            source ecosystem"),
            'link': 'https://codefund.app/',
            'img': static('v2/images/products/graphics-Codefund.svg'),
            'logo': static('v2/images/products/codefund-logo.svg'),
            'service_level': 'Self Service or Full Service',
            'traction': 'over 300mm impressions',
        },
        {
            'name': 'matching engine',
            'heading': _("Find the Right Dev. Every Time."),
            'description': _("It's not about finding *a* developer.  It's about finding *the right developer for your needs*. Our matching engine powers each of our products, and can target the right community members for you."),
            'link': '/users',
            'img': static('v2/images/products/engine.svg'),
            'logo': static('v2/images/products/engine-logo.png'),
            'service_level': 'Integrated',
            'traction': 'Matching 20k devs/mo',
        },
        {
            'name': 'labs',
            'heading': _("Tools for busy developers"),
            'description': _("Gitcoin Labs provides research reports and toolkits for busy developers, \
                            making Ethereum dapps fast, usable, and secure."),
            'link': '/labs',
            'img': static('v2/images/products/graphics-Labs.png'),
            'logo': static('v2/images/products/labs-logo.svg'),
            'service_level': 'Self Service',
            'traction': '12 Articles Shipped',
        }
    ]

    if settings.QUESTS_LIVE:
        products.append({
            'name': 'quests',
            'heading': _("Engaging Onboarding Experiences for the Web3 Ecosystem"),
            'description': _("Gitcoin Quests is a fun, gamified way to learn about the web3 ecosystem, earn rewards, and level up your decentralization-fu!"),
            'link': '/quests',
            'img': static('v2/images/products/graphics-Quests.png'),
            'logo': static('v2/images/products/quests-symbol.svg'),
            'service_level': 'Self Service',
            'traction': 'over 3000 plays/month',
        })

    default_back = get_leaderboard_back(request)
    back = request.GET.get('back', default_back[1])
    img = request.GET.get('img', default_back[0])

    context = {
        'is_outside': True,
        'active': 'products',
        'title': 'Products',
        'card_title': _("Gitcoin's Products."),
        'card_desc': _('At Gitcoin, we build products that allow for better incentivized collaboration \
                        in the realm of open source software'),
        'avatar_url': f"/static/v2/images/quests/backs/back{back}.jpeg",
        'back': back,
        'img': img,
        'products': products,
    }
    return TemplateResponse(request, 'products.html', context)

def not_a_token(request):
    """Render the not_a_token response."""
    context = {
        'is_outside': True,
        'active': 'not_a_token',
        'avatar_url': static('v2/images/no-token/no-token.jpg'),
        'title': 'Gitcoin is not a token',
        'card_title': _("Gitcoin is not a token"),
        'card_desc': _("We didn't do a token because we felt it wasn't the right way to align incentives \
                        with our user base.  Read more about the future of monetization in web3."),
    }
    return TemplateResponse(request, 'not_a_token.html', context)

def results(request, keyword=None):
    """Render the Results response."""
    if keyword and keyword not in programming_languages:
        raise Http404
    js = JSONStore.objects.get(view='results', key=keyword)
    context = js.data
    context['updated'] = js.created_on
    context['is_outside'] = True
    context['prefix'] = 'data-'
    import json
    context['avatar_url'] = static('v2/images/results_preview.gif')
    return TemplateResponse(request, 'results.html', context)

def get_specific_activities(what, trending_only, user, after_pk, request=None):
    # create diff filters
    activities = Activity.objects.filter(hidden=False).order_by('-created_on')
    view_count_threshold = 10

    is_auth = user and user.is_authenticated

    ## filtering
    relevant_profiles = []
    relevant_grants = []
    if what == 'tribes':
        relevant_profiles = get_my_earnings_counter_profiles(user.profile.pk) if is_auth else []
    elif what == 'all_grants':
        activities = activities.filter(grant__isnull=False)
    elif what == 'grants':
        relevant_grants = get_my_grants(user.profile) if is_auth else []
    elif what == 'my_threads' and is_auth:
        activities = user.profile.subscribed_threads.all().order_by('-created') if is_auth else []
    elif what == 'my_favorites' and is_auth:
        favorites = user.favorites.all().values_list('activity_id')
        activities = Activity.objects.filter(id__in=Subquery(favorites)).order_by('-created')
    elif 'keyword-' in what:
        keyword = what.split('-')[1]
        relevant_profiles = Profile.objects.filter(keywords__icontains=keyword)
    elif 'search-' in what:
        keyword = what.split('-')[1]
        view_count_threshold = 5
        base_filter = Q(metadata__icontains=keyword, activity_type__in=connect_types)
        keyword_filter = Q(pk=0) #noop
        if keyword == 'meme':
            keyword_filter = Q(metadata__type='gif') | Q(metadata__type='png') | Q(metadata__type='jpg')
        if keyword == 'meme':
            keyword_filter = Q(metadata__icontains='spotify') | Q(metadata__type='soundcloud') | Q(metadata__type='pandora')
        activities = activities.filter(keyword_filter | base_filter)
    elif 'tribe:' in what:
        key = what.split(':')[1]
        profile_filter = Q(profile__handle=key.lower())
        other_profile_filter = Q(other_profile__handle=key.lower())
        keyword_filter = Q(metadata__icontains=key)
        activities = activities.filter(keyword_filter | profile_filter | other_profile_filter)
    elif 'activity:' in what:
        view_count_threshold = 0
        pk = what.split(':')[1]
        activities = Activity.objects.filter(pk=pk)
        if request:
            page = int(request.GET.get('page', 1))
            if page > 1:
                activities = Activity.objects.none()
    elif 'hackathon:' in what:
        pk = what.split(':')[1]
        activities = activities.filter(activity_type__in=connect_types).filter(Q(hackathonevent=pk) | Q(bounty__event=pk))
    elif ':' in what:
        pk = what.split(':')[1]
        key = what.split(':')[0] + "_id"
        if key == 'activity_id':
            key = 'pk'
        kwargs = {}
        kwargs[key] = pk
        activities = activities.filter(**kwargs)

    # filters
    if len(relevant_profiles):
        activities = activities.filter(profile__in=relevant_profiles)
    if len(relevant_grants):
        activities = activities.filter(grant__in=relevant_grants)
    if what == 'connect':
        activities = activities.filter(activity_type__in=connect_types)
    if what == 'kudos':
        activities = activities.filter(activity_type__in=['new_kudos', 'receive_kudos'])

    # after-pk filters
    if after_pk:
        activities = activities.filter(pk__gt=after_pk)
    if trending_only:
        if what == 'everywhere':
            view_count_threshold = 40
        activities = activities.filter(view_count__gt=view_count_threshold)

    return activities

def activity(request):
    """Render the Activity response."""
    page_size = 7
    page = int(request.GET.get('page', 1))
    what = request.GET.get('what', 'everywhere')
    trending_only = int(request.GET.get('trending_only', 0))

    activities = get_specific_activities(what, trending_only, request.user, request.GET.get('after-pk'), request)
    activities = activities.prefetch_related('profile', 'likes', 'comments', 'kudos', 'grant', 'subscription', 'hackathonevent')

    # store last seen
    if activities.exists():
        last_pk = activities.first().pk
        current_pk = request.session.get(what)
        next_pk = last_pk if (not current_pk or current_pk < last_pk) else current_pk
        request.session[what] = next_pk
    # pagination
    next_page = page + 1
    start_index = (page-1) * page_size
    end_index = page * page_size

    #p = Paginator(activities, page_size)
    #page = p.get_page(page)
    page = activities[start_index:end_index]
    suppress_more_link = not len(page)

    # increment view counts
    activities_pks = [obj.pk for obj in page]
    if len(activities_pks):
        increment_view_counts.delay(activities_pks)

    context = {
        'suppress_more_link': suppress_more_link,
        'what': what,
        'next_page': next_page,
        'page': page,
        'target': f'/activity?what={what}&trending_only={trending_only}&page={next_page}',
        'title': _('Activity Feed'),
        'my_tribes': list(request.user.profile.tribe_members.values_list('org__handle',flat=True)) if request.user.is_authenticated else [],
    }
    context["activities"] = [a.view_props_for(request.user) for a in page]

    return TemplateResponse(request, 'activity.html', context)

@ratelimit(key='ip', rate='30/m', method=ratelimit.UNSAFE, block=True)
def create_status_update(request):
    issue_re = re.compile(r'^(?:https?://)?(?:github\.com)/(?:[\w,\-,\_]+)/(?:[\w,\-,\_]+)/issues/(?:[\d]+)')
    response = {}

    if request.POST:
        profile = request.user.profile
        title = request.POST.get('data')
        resource = request.POST.get('resource', '')
        provider = request.POST.get('resourceProvider', '')
        resource_id = request.POST.get('resourceId', '')

        kwargs = {
            'activity_type': 'status_update',
            'metadata': {
                'title': title,
                'ask': request.POST.get('ask'),
                'fund_able': provider and issue_re.match(provider) != None,
                'resource': {
                    'type': resource,
                    'provider': provider,
                    'id': resource_id
                }
            }
        }

        if resource == 'content':
            meta = kwargs['metadata']['resource']
            meta['title'] = request.POST.get('title', '')
            meta['description'] = request.POST.get('description', '')
            meta['image'] = request.POST.get('image', '')

        kwargs['profile'] = profile
        if ':' in request.POST.get('what'):
            what = request.POST.get('what')
            key = what.split(':')[0]
            result = what.split(':')[1]
            if key and result:
                key = f"{key}_id"
                kwargs[key] = result
                kwargs['activity_type'] = 'wall_post'

        if request.POST.get('has_video'):
            kwargs['metadata']['video'] = True
            kwargs['metadata']['gfx'] = request.POST.get('video_gfx')

        if request.POST.get('option1'):
            poll_choices = []
            for i in range(1, 5):
                key = "option" + str(i)
                val = request.POST.get(key)
                if val:
                    poll_choices.append({
                        'question': val,
                        'answers': [],
                        'i': i,
                        })
            kwargs['metadata']['poll_choices'] = poll_choices

        if ':' in request.POST.get('tab', ''):
            tab = request.POST.get('tab')
            key = tab.split(':')[0]
            result = tab.split(':')[1]
            if key == 'hackathon':
                kwargs['hackathonevent'] = HackathonEvent.objects.get(pk=result)
            if key == 'tribe':
                kwargs['other_profile'] = Profile.objects.get(handle=result.lower())

        try:
            activity = Activity.objects.create(**kwargs)
            response['status'] = 200
            response['message'] = 'Status updated!'

            mentioned_profiles = get_profiles_from_text(title).exclude(user__in=[request.user])
            to_emails = set(mentioned_profiles.values_list('email', flat=True))
            mention_email(activity, to_emails)

            if kwargs['activity_type'] == 'wall_post':
                if 'Email Grant Funders' in activity.metadata.get('ask'):
                    grant_update_email_task.delay(activity.pk)
                else:
                    wall_post_email(activity)

        except Exception as e:
            response['status'] = 400
            response['message'] = 'Bad Request'
            logger.error('Status Update error - Error: (%s) - Handle: (%s)', e, profile.handle if profile else '')
            return JsonResponse(response, status=400)
    return JsonResponse(response)

def grant_redir(request):
    return redirect('/grants/')

def help(request):
    return redirect('/wiki/')

def verified(request):
    user = request.user if request.user.is_authenticated else None
    profile = request.user.profile if user and hasattr(request.user, 'profile') else None

    context = {
        'active': 'verified',
        'title': _('Verified'),
        'profile': profile,
    }
    return TemplateResponse(request, 'verified.html', context)

def presskit(request):

    brand_colors = [
        (
            "Cosmic Teal",
            "#25e899",
            "37, 232, 153"
        ),
        (
            "Dark Cosmic Teal",
            "#0fce7c",
            "15, 206, 124"
        ),
        (
            "Milky Way Blue",
            "#15003e",
            "21, 0, 62"
        ),
        (
            "Stardust Yellow",
            "#FFCE08",
            "255,206, 8"
        ),
        (
            "Polaris Blue",
            "#3E00FF",
            "62, 0, 255"
        ),
        (
            "Vinus Purple",
            "#8E2ABE",
            "142, 42, 190"
        ),
        (
            "Regulus Red",
            "#F9006C",
            "249, 0, 108"
        ),
        (
            "Star White",
            "#FFFFFF",
            "23, 244, 238"
        ),
    ]

    context = {
        'brand_colors': brand_colors,
        'active': 'get',
        'title': _('Presskit'),
    }
    return TemplateResponse(request, 'presskit.html', context)

def handler403(request, exception=None):
    return error(request, 403)

def handler404(request, exception=None):
    return error(request, 404)

def handler500(request, exception=None):
    return error(request, 500)

def handler400(request, exception=None):
    return error(request, 400)

def error(request, code):
    context = {
        'active': 'error',
        'code': code,
        'nav': 'home',
    }
    context['title'] = "Error {}".format(code)
    return_as_json = 'api' in request.path

    if return_as_json:
        return JsonResponse(context, status=500)
    return TemplateResponse(request, 'error.html', context, status=code)

def portal(request):
    return redirect('https://gitcoin.co/help')

def community(request):
    return redirect('https://github.com/gitcoinco/community')

def onboard(request):
    return redirect('https://docs.google.com/document/d/1DQvek5TwASIp1njx5VZeLKEgSxfvxm871vctx1l_33M/edit?')

def podcast(request):
    return redirect('https://itunes.apple.com/us/podcast/gitcoin-community/id1360536677')

def feedback(request):
    return redirect('https://goo.gl/forms/9rs9pNKJDnUDYEeA3')

def wallpaper(request):
    return redirect('https://gitcoincontent.s3-us-west-2.amazonaws.com/Wallpapers.zip')

def help_dev(request):
    return redirect('/wiki')

def help_pilot(request):
    return redirect('/wiki')

def help_repo(request):
    return redirect('/wiki')

def help_faq(request):
    return redirect('/wiki')

def browser_extension_chrome(request):
    return redirect('https://chrome.google.com/webstore/detail/gdocmelgnjeejhlphdnoocikeafdpaep')

def browser_extension_firefox(request):
    return redirect('https://addons.mozilla.org/en-US/firefox/addon/gitcoin/')

def itunes(request):
    return redirect('https://itunes.apple.com/us/app/gitcoin/id1319426014')

def casestudy(request):
    return redirect('https://docs.google.com/document/d/1M8-5xCGoJ8u-k0C0ncx_dr9LtHwZ32Ccn3KMFtEnsBA/edit')

def schwag(request):
    return redirect('https://goo.gl/forms/X3jAtOVUUNAumo072')

def slack(request):
    context = {
        'active': 'slack',
        'msg': None,
        'nav': 'home',
    }

    if request.POST:
        email = request.POST.get('email')
        context['msg'] = _('You must provide an email address')
        if email:
            context['msg'] = _('Your invite has been sent.')
            context['success'] = True
            try:
                validate_email(email)
                get_or_save_email_subscriber(email, 'slack', send_slack_invite=False)
                response = invite_to_slack(email)

                if not response.get('ok'):
                    context['msg'] = response.get('error', _('Unknown error'))
                context['success'] = False
            except ValidationError:
                context['msg'] = _('Invalid email')

    return TemplateResponse(request, 'slack.html', context)

@csrf_exempt
def newtoken(request):
    context = {
        'active': 'newtoken',
        'msg': None,
    }

    if request.POST:
        required_fields = ['email', 'terms', 'not_security', 'address', 'symbol', 'decimals', 'network']
        validtion_passed = True
        for key in required_fields:
            if not request.POST.get(key):
                context['msg'] = str(_('You must provide the following fields: ')) + key
                validtion_passed = False
        if validtion_passed:
            obj = Token.objects.create(
                address=request.POST['address'],
                symbol=request.POST['symbol'],
                decimals=request.POST['decimals'],
                network=request.POST['network'],
                approved=False,
                priority=1,
                metadata={
                    'ip': get_ip(request),
                    'email': request.POST['email'],
                    }
                )
            new_token_request(obj)
            context['msg'] = str(_('Your token has been submitted and will be listed within 2 business days if it is accepted.'))

    return TemplateResponse(request, 'newtoken.html', context)

def btctalk(request):
    return redirect('https://bitcointalk.org/index.php?topic=2206663')

def reddit(request):
    return redirect('https://www.reddit.com/r/gitcoincommunity/')

def blog(request):
    return redirect('https://gitcoin.co/blog')

def livestream(request):
    return redirect('https://calendar.google.com/calendar/r?cid=N3JxN2dhMm91YnYzdGs5M2hrNjdhZ2R2ODhAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ')

def twitter(request):
    return redirect('http://twitter.com/gitcoin')

def fb(request):
    return redirect('https://www.facebook.com/GetGitcoin/')

def medium(request):
    return redirect('https://medium.com/gitcoin')

def refer(request):
    return redirect('https://gitcoin.co/funding/details?url=https://github.com/gitcoinco/gitcoinco/issues/1')

def gitter(request):
    return redirect('https://gitter.im/gitcoinco/Lobby')

def github(request):
    return redirect('https://github.com/gitcoinco/')

def youtube(request):
    return redirect('https://www.youtube.com/channel/UCeKRqRjzSzq5yP-zUPwc6_w')

def web3(request):
    return redirect('https://www.youtube.com/watch?v=cZZMDOrIo2k')

@cached_view_as(Token.objects.filter(network=get_default_network, approved=True))
def tokens(request):
    context = {}
    networks = ['mainnet', 'ropsten', 'rinkeby', 'unknown', 'custom']
    for network in networks:
        key = f"{network}_tokens"
        context[key] = Token.objects.filter(network=network, approved=True)
    return TemplateResponse(request, 'tokens_js.txt', context, content_type='text/javascript')

@csrf_exempt
@ratelimit(key='ip', rate='5/m', method=ratelimit.UNSAFE, block=True)
def increase_funding_limit_request(request):
    user = request.user if request.user.is_authenticated else None
    profile = request.user.profile if user and hasattr(request.user, 'profile') else None
    usdt_per_tx = request.GET.get('usdt_per_tx', None)
    usdt_per_week = request.GET.get('usdt_per_week', None)
    is_staff = user.is_staff if user else False

    if is_staff and usdt_per_tx and usdt_per_week:
        try:
            profile_pk = request.GET.get('profile_pk', None)
            target_profile = Profile.objects.get(pk=profile_pk)
            target_profile.max_tip_amount_usdt_per_tx = usdt_per_tx
            target_profile.max_tip_amount_usdt_per_week = usdt_per_week
            target_profile.save()
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=400)

        return JsonResponse({'msg': _('Success')}, status=200)

    if request.body:
        if not user or not profile or not profile.handle:
            return JsonResponse(
                {'error': _('You must be Authenticated via Github to use this feature!')},
                status=401)

        try:
            result = FundingLimitIncreaseRequestForm(json_parse(request.body))
            if not result.is_valid():
                raise
        except Exception as e:
            return JsonResponse({'error': _('Invalid JSON.')}, status=400)

        new_funding_limit_increase_request(profile, result.cleaned_data)

        return JsonResponse({'msg': _('Request received.')}, status=200)

    form = FundingLimitIncreaseRequestForm()
    params = {
        'form': form,
        'title': _('Request a Funding Limit Increase'),
        'card_title': _('Gitcoin - Request a Funding Limit Increase'),
        'card_desc': _('Do you hit the Funding Limit? Request a increasement!')
    }

    return TemplateResponse(request, 'increase_funding_limit_request_form.html', params)

@staff_member_required
def tribes(request):
    plans= [
        {
            'type': 'lite',
            'img': static('v2/images/tribes/landing/plan-lite.svg'),
            'price': '10k',
            'features': [
                '1 Hackthon Credit'
            ],
            'features_na': [
                'Access to Gitcoin Pro Tools'
            ]
        },
        {
            'type': 'pro',
            'img': static('v2/images/tribes/logo.svg'),
            'discount': '40%',
            'price': '6k',
            'features': [
                {
                    'title': '3 Hackathon Credits',
                    'info': '18k year total'
                },
                'Access to Gitcoin Pro Tools'
            ]
        },
        {
            'type': 'launch',
            'img': static('v2/images/tribes/landing/plan-launch.svg'),
            'price': '4k',
            'features': [
                {
                    'title': '5 Hackathon Credits',
                    'info': '20k year total'
                },
                'Access to Gitcoin Pro Tools'
            ]
        }
    ]

    tribes = JSONStore.objects.get(view='tribes', key='tribes').data

    testimonials = [
        {
            'text': 'I had a lot of fun (during Beyond Blockchain) meeting people and building tangible rapidly. Glad to have a winning submission!',
            'author': 'VirajA',
            'designation': 'Hacker',
            'photo': static('v2/images/tribes/landing/viraj.png')
        },
        {
            'text': 'Gitcoin has a fantastic community that is our target audience -- Web 3 developers who want to build.',
            'author': 'Sam Williams',
            'designation': 'CEO, Arweave',
            'photo':  static('v2/images/tribes/landing/sam.jpg'),
            'org_photo': static('v2/images/project_logos/arweave.svg')
        },
        {
            'text': 'Relationships with developers" is our guiding light. For both developers and ourselves, it’s great to work with GItcoin to see more working examples using Portis.',
            'author': 'Scott Gralnick',
            'designation': 'Co-Founder, Portis',
            'photo': static('v2/images/tribes/landing/scott.png'),
            'org_photo': static('v2/images/project_logos/portis.png')
        }
    ]

    reasons = [
        {
            'title': 'Hackathon',
            'img': static('v2/images/tribes/landing/hackathon.svg'),
            'info': 'See meaningful projects come to life on your dapp'
        },
        {
            'title': 'Suggest Bounty',
            'img': static('v2/images/tribes/landing/suggest.svg'),
            'info': 'Get bottoms up ideas from passionate contributors'
        },
        {
            'title': 'Grow Tribe',
            'img': static('v2/images/tribes/landing/grow.svg'),
            'info': 'Work seamlessly with your core contributors'
        },
        {
            'title': 'Workshops',
            'img': static('v2/images/tribes/landing/workshop.svg'),
            'info': 'Host workshops and learn together'
        },
        {
            'title': 'Chat',
            'img': static('v2/images/tribes/landing/chat.svg'),
            'info': 'Direct connection to your trusted tribe'
        },
        {
            'title': 'Town Square',
            'img': static('v2/images/tribes/landing/townsquare.svg'),
            'info': 'Broadcast your priorities and engagey our tribe'
        },
        {
            'title': 'Payout/Fund',
            'img': static('v2/images/tribes/landing/payout.svg'),
            'info': 'Easily co-manage hackathons with your team'
        },
        {
            'title': 'Stats Report',
            'img': static('v2/images/tribes/landing/stats.svg'),
            'info': 'See how your hackathons are performing'
        }
    ]

    context = {
        'plans': plans,
        'tribes': tribes,
        'testimonials': testimonials,
        'reasons': reasons
    }

    return TemplateResponse(request, 'tribes/landing.html', context)


import os
import json
import numpy as np

# Torch imports
import torch

from pprint import pprint
from common.WavefrontOBJ import *
import igl

def grouped(iterable, n):
    "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
    return zip(*[iter(iterable)] * n)

#
# Function to save 3D mesh
#
def save_mesh(path, verts, index, faces, normals):
    mverts = verts #np.reshape(verts, (-1, 3))
    mnorms = np.reshape(normals, (-1, 3))

    print('verts.shape: ', mverts.shape)
    mesh = WavefrontOBJ()
    mesh.vertices = mverts
    mesh.normals = mnorms
    mesh.polygons = faces
    save_obj(mesh, path % (index))
    print('Mesh OBJ saved: ', path % (index))

#
# Function to load OBJ files of 3D meshes
#
def load_all_meshes_to_matrixv2(path_list, path_index_list, labels_list , centre_meshes=False, pattern_out=None):
    # Outputs
    vertices        = 0
    centres         = 0
    faces           = {}
    normals         = 0
    masks           = 0

    vertex_count    = 0
    file_count      = 0

    files_list      = path_list.split(" ")
    label_list      = labels_list.split(" ")
    indices_list    = path_index_list.split()

    frame_start     = 0
    frame_end       = 0
    sequenceLength  = 1

    meshList    = []
    colours     = []
    labels      = []
    laplace     = {}

    sequence_index = 0

    for (start, end), file in zip( grouped(indices_list, 2), files_list):
        current_label = label_list[sequence_index]

        for frame in range(int(start), int(end) +1):
            if file.endswith(".obj"):
                mesh_path = (file % frame)
                if os.path.isfile(mesh_path):
                    if current_label not in laplace:
                        v, f = igl.read_triangle_mesh(mesh_path)
                        l = igl.cotmatrix(v, f)
                        laplace[current_label] = []
                    if current_label not in faces:
                        mesh = load_obj(mesh_path)
                        faces[current_label] = mesh.polygons

                    meshList.append(mesh_path)
                    labels.append(current_label)
                    #print("Loaded ", mesh_path)

        sequence_index = sequence_index + 1
    return meshList, colours, labels, faces, laplace

def load_mesh_to_matrix(path_list, vertex_count,Only_vert=False):
    mesh = load_obj(path_list)
    verts = mesh.vertices
    norms = mesh.normals
    faces = mesh.polygons

    vertices = np.zeros([vertex_count])
    normals = np.zeros([vertex_count])
    mask = np.zeros([vertex_count])

    # Reshape and add to array (x,y,z,1,x,y,z,1,x,y,...)
    flaten = lambda l: [item for sublist in l for item in sublist]

    flat_verts = flaten(verts)
    flat_norms = flaten(norms)

    vertices[:len(flat_verts)] = flat_verts
    normals[:len(flat_norms)] = flat_norms
    mask[:len(flat_verts)] = np.ones([len(flat_verts)])
    if Only_vert:
        return vertices
    else :
        return vertices, normals, faces, mask


'''
Created by auto_sdk on 2016.05.10
'''
from top.api.base import RestApi
class AlibabaBaichuanAppcontentUploadRequest(RestApi):
	def __init__(self,domain='gw.api.taobao.com',port=80):
		RestApi.__init__(self,domain, port)
		self.appid = None
		self.bizid = None
		self.operate = None
		self.params = None

	def getapiname(self):
		return 'alibaba.baichuan.appcontent.upload'


# -*- coding: utf-8 -*-
"""
URLs for Api Collection list app
"""

from django.conf.urls import url
from .views import ApiCollectionListView, ExportCsvView

urlpatterns = [
    url(r'^$',
        ApiCollectionListView.as_view(),
        name='apicollection-list'),
    url(r'^export_csv$',
        ExportCsvView.as_view(),
        name='export-csv-apicollection')
]


import pandas as pd
import numpy as np
import os
import nltk
import sys
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from scipy import sparse

import texthero as hero
from texthero import preprocessing
from nltk import FreqDist
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn import metrics
import nltk
# nltk.download('punkt')
# nltk.download('averaged_perceptron_tagger')
from collections import Counter

from mpl_toolkits.mplot3d import Axes3D
import math

pd.set_option('mode.chained_assignment', None)

np.set_printoptions(threshold=10)

F = [0.075, 0.2, 0.5,0.75, 1]
# F = [0.075]

profiles = pd.read_csv('profiles.csv',sep=',',nrows = 10000)
df = profiles
df.loc[df.sex == 'm', 'sex'] = 1
df.loc[df.sex == 'f', 'sex'] = 0

#clean essays (how?)
essays=['essay0','essay1','essay2','essay3','essay4','essay5','essay6','essay7','essay8','essay9']
# df = profiles[essays]
for i in essays:
    profiles[i] = hero.clean(profiles[i])
    profiles[i] = [n.replace('br','') for n in profiles[i]]

Test_ac = []
Test_er = []
Train_ac = []
Train_er = []

#different fraction of data
for t_frac , K in zip(F, [[50], [200], [200], [500], [500]]) :
    print('t_frac',t_frac)
    temp = profiles.sample(frac = t_frac,  random_state = 32)
    pf = temp.copy()

    test_ac = []
    train_ac = []

    #split training and testing
    S = np.array_split(pf, 10)
    for ite in range(10):
        print('ite', ite)

        testSet = S[ite]
        temp = pf.drop(testSet.index)
        trainingSet = temp.copy()

        #---------work on training data
        df = trainingSet[essays]
        #combine 9 essays of every person
        df['dumb'] = np.zeros(len(df))
        df['row essays'] = df['essay0'] + " " + df['essay1'] + " " + df['essay2'] + " " + df['essay3'] + " " + df['essay4'] + " " + df['essay5'] + " " + df['essay6'] + " " + df['essay7'] + " " + df['essay8'] + " " + df['essay9']
        df = df.drop(columns = essays)

        df_essays_per_person = df.drop(columns = ['dumb'])
        df_essays_per_person.to_csv('essays_per_person.csv', sep=',',  index=False)

        #combine all essays
        df_essay_all_persons = df.groupby('dumb')['row essays'].apply(' '.join).reset_index()
        df_essay_all_persons = df_essay_all_persons.drop(columns = ['dumb'])
        df_essay_all_persons.to_csv('essay_all_persons.csv', sep=',',  index=False)

        #build vocabulary array of df_essay_all_persons
        string = df_essay_all_persons.iloc[0]['row essays']

        tokens = nltk.word_tokenize(string)
        tags = nltk.pos_tag(tokens)
        voc_pos_dict = Counter( tag for word,  tag in tags)
        voc_list = list(voc_pos_dict.keys())

        #build vocabulary frequency dictionaries of each person
        dict_traing_each_person = []
        for i in range(len(df)):
            # print(i)
            string = df.iloc[i]['row essays']
            tokens = nltk.word_tokenize(string)
            tags = nltk.pos_tag(tokens)
            dict_ = Counter( tag for word,  tag in tags)
            dict_traing_each_person.append(dict_)

        #convert training data essays into word frequencies
        X_train = np.zeros((len(df), len(voc_list)))
        for i in range(len(df)):
            # print('0', i)
            for j in range(len(voc_list)):
                if voc_list[j] in dict_traing_each_person[i]:
                    X_train[i][j] = dict_traing_each_person[i][voc_list[j]]

        Y_train = trainingSet.loc[:,['sex']].values
        Y_train = Y_train.astype(int)
        Y_train = Y_train.T
        Y_train = Y_train.flatten()

        #---------work on testSet
        df = testSet[essays]
        #combine 9 essays of every person
        df['dumb'] = np.zeros(len(df))
        df['row essays'] = df['essay0'] + " " + df['essay1'] + " " + df['essay2'] + " " + df['essay3'] + " " + df['essay4'] + " " + df['essay5'] + " " + df['essay6'] + " " + df['essay7'] + " " + df['essay8'] + " " + df['essay9']
        df = df.drop(columns = essays)

        df_essays_per_person = df.drop(columns = ['dumb'])
        df_essays_per_person.to_csv('essays_per_person.csv', sep=',',  index=False)

        #build vocabulary frequency dictionaries of each person
        dict_test_each_person = []
        for i in range(len(df)):
            # print('2',i)
            string = df.iloc[i]['row essays']
            tokens = nltk.word_tokenize(string)
            tags = nltk.pos_tag(tokens)
            dict_ = Counter( tag for word,  tag in tags)
            dict_test_each_person.append(dict_)

        #convert test data essays into word frequencies
        X_test = np.zeros((len(df), len(voc_list)))
        for i in range(len(df)):
            # print('3',i)
            for j in range(len(voc_list)):
                if voc_list[j] in dict_test_each_person[i]:
                    X_test[i][j] = dict_test_each_person[i][voc_list[j]]

        Y_test = testSet.loc[:,['sex']].values
        Y_test = Y_test.astype(int)
        Y_test = Y_test.T
        Y_test = Y_test.flatten()

        #----------PCA
        # Standardizing the features
        X_train = StandardScaler().fit_transform(X_train)
        # np.savetxt("X_train.csv", X_train, delimiter = ",")
        X_test = StandardScaler().fit_transform(X_test)

        pca = PCA(.95)
        pca.fit(X_train)

        X_train = pca.transform(X_train)
        X_test = pca.transform(X_test)

        aa =  pca.explained_variance_ratio_

        # #plot first three Principle components
        # x = X_train[:, 0]
        # y = X_train[:, 1]
        # z = X_train[:, 2]

        # group = Y_train
        # cdict = {0: 'red', 1: 'blue'}

        # fig = plt.figure()
        # ax = Axes3D(fig)
        # for g in np.unique(group):
        #     ix = np.where(group == g)
        #     ax.scatter(x[ix], y[ix], z[ix], c = cdict[g], label = g, s = 30, alpha=0.5)

        # ax.set_zlabel('Third Principle Component', fontdict={'size': 15})
        # ax.set_ylabel('Second Principle Component', fontdict={'size': 15})
        # ax.set_xlabel('First Principle Component', fontdict={'size': 15})

        # ax.legend()
        # plt.show()

        #------------kmeans

        sil_score_max = -1 #this is the minimum possible score

        distortions = []

        for i in K:

            # print(i)
            km = KMeans(
                n_clusters=i, init='random',  max_iter=300,

            ).fit(X_train)

            Cluster_train = km.labels_
            Cluster_test = km.predict(X_test)
            distortions.append(km.inertia_)
            sil_score = silhouette_score(X_train, Cluster_train)
            # print("s SCORE",i ,sil_score)
            k = i

        # print('sex_cluster',cluster_sex)

        # # plot
        # fig3, ax3 = plt.subplots()
        # plt.plot(K, distortions, marker='o')
        # plt.title('Fraction = ' + str(t_frac))
        # plt.xlabel('Number of clusters')
        # plt.ylabel('WC-SSD')
        # plt.show()

        #assign gender to each cluster
        cluster_sex_train = np.array([Cluster_train, Y_train])
        cluster_sex_train = cluster_sex_train.T

        cluster_sex_map = []
        for i in range(k):
            cluster = cluster_sex_train[cluster_sex_train[:,0] == i, :]
            sex = cluster[:,1]
            sex = np.mean(sex)
            # cluster_sex_map.append(sex)
            if sex >= 0.5:
                cluster_sex_map.append(1)
            else:
                cluster_sex_map.append(0)

        #look at testset and calculate sex prediction accuracy

        n_match = 0

        # for i in range(len(Cluster_test)):

        #     p = cluster_sex_map[Cluster_test[i]]
        #     rand_sex = np.random.binomial(1, p, 1)

        #     if rand_sex[0] == Y_test[i]:
        #         n_match += 1

        for i in range(len(Cluster_test)):
            if cluster_sex_map[Cluster_test[i]] == Y_test[i]:
                n_match += 1

        test_acc = n_match/len(Cluster_test)
        test_ac.append(test_acc)
        # print(test_acc)

        #look at training and calculate sex prediction accuracy
        n_match = 0
        for i in range(len(Cluster_train)):
            if cluster_sex_map[Cluster_train[i]] == Y_train[i]:
                n_match += 1

        train_acc = n_match/len(Cluster_train)
        train_ac.append(train_acc)
        # print(train_acc)

    #calculate mean of test and train acc and error after 10 fold CV
    Test_ac.append(np.mean(test_ac))
    Test_er.append(np.std(test_ac)/math.sqrt(10))
    Train_ac.append(np.mean(train_ac))
    Train_er.append(np.std(train_ac)/math.sqrt(10))

    print('test_ac',test_ac)
    print('train_ac',train_ac)

#plot acc over number of samples
fig2, ax2 = plt.subplots()

plt.xlabel('Training Examples')
plt.ylabel('Model Accuracy')

n_samples = [element * 9000 for element in F]

plt.plot(n_samples,Test_ac,label="Test Accuracy")
plt.errorbar(n_samples,Test_ac,yerr=Test_er,fmt='o',ecolor='r',color='b',elinewidth=2,capsize=4)
print('Train_er',Train_er)
print('Test_er',Test_er)

plt.plot(n_samples,Train_ac,label="Training Accuracy")
plt.errorbar(n_samples,Train_ac,yerr=Train_er,fmt='o',ecolor='r',color='b',elinewidth=2,capsize=4)

plt.legend(loc=[0.5, 1], prop={'size': 12})

Machine learning/Predicting gender using Tinder profile/colab_notebooks-20201217T063810Z-001/Kmeans.py


from flask import Flask, render_template, url_for, request, redirect,jsonify
from flask_sqlalchemy import SQLAlchemy
import queries
import sqlite3
import pandas as pd
import pickle

import warnings
warnings.filterwarnings("ignore")

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///customer.db'
db = SQLAlchemy(app)

class customers(db.Model):
    ID = db.Column(db.Integer, primary_key=True)
    Name = db.Column(db.String(200), nullable=False)
    Age = db.Column(db.Integer)

    def __repr__(self):
        return '<Task %r>' % self.ID

result = {}

def get_by_Name(Name):
    conn = sqlite3.connect('customer.db')
    cur = conn.cursor()
    statement = "SELECT * FROM customers WHERE Name = ?"
    cur.execute(statement, [Name])
    cust_details = cur.fetchall()
    return cust_details

def predict(body):
    # body = body.split(",")
    # body = [float(i) for i in body]

    # df = pd.DataFrame([body])

    filename = 'linear_regression_model.sav'
    loaded_model = pickle.load(open(filename, 'rb'))
    Y_pred_lr = loaded_model.predict(body)

    return Y_pred_lr

@app.route("/")
def index():
    tasks = customers.query.limit(5).all()
    return render_template('index.html', tasks=tasks)

@app.route("/Name", methods = ["GET"])
def get_cust():
    global sent_global
    body = request.args.get('Name')
    sent = get_by_Name(body)
    sent_global = get_by_Name(body)
    sent_global = [list(l) for l in sent_global]
    print(sent_global)
    return render_template('update.html', sent=sent)

@app.route("/Predict", methods = ["GET"])
def age_predict():
    body = request.args.get('Predict')
    df = pd.DataFrame(sent_global)
    df = pd.get_dummies(df)

    df['new'] = 0  # have to remove it
    print(df)
    sent_predict = predict(df)
    print(sent_predict)
    return render_template('update.html', sent_predict=sent_predict)

if __name__ == "__main__":
    app.run(host='127.0.0.13', port=8080, debug=True)


from movements import app
from movements.forms import MovementForm
from flask import Flask, render_template, request, url_for, redirect
import sqlite3
from datetime import date, datetime
import time
import requests #from requests.exceptions import ConnectionError, Timeout, TooManyRedirects
import json
import numpy as np
import matplotlib.pyplot as plt

API_KEY =  app.config['API_KEY']
DBFILE = app.config['DBFILE']

def consulta(query, params=()):
    ## función 1: establecer conexión con sqlite3
    conn = sqlite3.connect(DBFILE)
    c = conn.cursor()
    c.execute(query, params)
    conn.commit()
    filas = c.fetchall()
    conn.close

    ## función 2: dar formato a la consulta como lista de diccionarios
    if len(filas) == 0:
        return filas

    columnNames = []
    for columnName in c.description:
        columnNames.append(columnName[0])

    listaDeDiccionarios = []

    for fila in filas:
        d = {}
        for ix, columnName in enumerate(columnNames): # enumerate() te da una tupla con el índice y el elemento.
            d[columnName] = fila[ix]
        listaDeDiccionarios.append(d)

    return listaDeDiccionarios

def peticionAPI(specific_url):
    response = requests.get(specific_url)
    if response.status_code == 200:
        api = response.json()
        return api
    else: #(ConnectionError, Timeout, TooManyRedirects) as e:
        raise Exception("Problema de consulta tipo {}".format(response.status_code))

def calc_monedero():
    lista_monedas = ['BTC','ADA','BCH','BSV','EOS','ETH','LTC','BNB','TRX','USDT','XLM','XRP']
    monedero = {} # cuantas monedas tengo de cada cripto. No incluye EUR.
    for moneda in lista_monedas:
        query = "SELECT sum(case when to_currency = ? then to_quantity else 0 end) - sum(case when  from_currency = ? then from_quantity else 0 end) as saldo_moneda FROM movements;"
        tmp = consulta(query, (moneda, moneda))
        saldo = tmp[0]['saldo_moneda']
        monedero[moneda] = saldo
    return monedero

def validarConversion(amount, simbolo, convert):
    monedero = calc_monedero()
    error = None
    try:
        if float(amount) <= 0:
            error = 'Cifra no válida. Entre cantidad superior a 0.'
            return error
    except:
        error = 'Cifra no válida. Use el punto para separar decimales. No se admiten otros símbolos.'
        return error

    if simbolo != 'EUR' and monedero[simbolo] < float(amount):
        error = 'Sólo dispone de {:.4f} {} para gastar. Consulte el monedero para ver la cantidad real.'.format(monedero[simbolo], simbolo)
        return error

    if simbolo == convert:
        error = 'Las monedas From y To deben ser diferentes.'
        return error

    if simbolo == 'EUR' and convert != 'BTC':
        error = 'Con EUR sólo puedes comprar BTC.'
        return error

    if simbolo != 'BTC' and convert == 'EUR':
        error = 'Sólo puede comprar EUR con BTC.'
        return error

@app.route('/')
def listaMovimientos(): # mostrar tabla SQL
    query = "SELECT date, time, from_currency, from_quantity, to_currency, to_quantity, from_quantity/to_quantity as precio_unitario_to FROM movements;"
    mensaje = ""
    try:
        compras = consulta(query)
    except Exception as e:
        print("**ERROR**: Acceso base de datos - {}".format(type(e).__name__))
        mensaje = "Error en acceso a la base de datos. Consulte con el administrador."
        return render_template('movementsList.html', error=mensaje)

    monedero_actual = calc_monedero()
    return render_template('movementsList.html', datos=compras, monedero=monedero_actual, error=mensaje)

@app.route('/purchase', methods=['GET', 'POST'])
def purchase():
    # 1) Formulario vacío:
    if request.method == 'GET':
        form_vacio = MovementForm()
        try:
            monedero = calc_monedero()
        except Exception as e:
            print("**ERROR**: Acceso base de datos - {}".format(type(e).__name__))
            mensaje = "Error en acceso a la base de datos. Consulte con el administrador."
            return render_template('movementsList.html', error=mensaje)

        lista_from = ['EUR'] # crear una lista de monedas disponibles para FROM: EUR + las que tengan cantidad > 0 en mi monedero

        try:
            for moneda, q in monedero.items():
                if q>0:
                    lista_from.append(moneda)
            form_vacio.from_currency.choices = lista_from # choices necesita una lista
        except:
            monedero = 'vacio'
            form_vacio.from_currency.choices = lista_from

        return render_template('purchase.html', form=form_vacio, vacio='yes', monedero=monedero)

    else: #2) request.method == 'POST': Grabar o Calcular
        form = MovementForm()
        form.from_currency.choices = [request.form.get('from_currency')] # bloqueamos la lista FROM con  la moneda elegida
        form.to_currency.choices = [request.form.get('to_currency')] # bloqueamos la lista TO con  la moneda elegida
        monedero = calc_monedero()

        if  request.form.get('submit') == 'Grabar' and form.validate():
            try:
                query = "INSERT INTO movements (date, time, from_currency, from_quantity, to_currency, to_quantity) VALUES (?,?,?,?,?,?);"
                consulta(query, (request.form.get("date"), request.form.get("time"), request.form.get("from_currency"),
                                request.form.get("from_quantity"), request.form.get("to_currency"), request.form.get("to_quantity")))

                return redirect(url_for('listaMovimientos'))
            except:
                error = "Error: Debe efectuar el cálculo (botón calculadora) antes de validar la compra."
                return render_template('purchase.html', form=form, vacio='yes', error=error, monedero=monedero)
        else:
            amount = request.form.get('from_quantity') # x "simbolo" convierte a "convert"
            simbolo = request.form.get('from_currency')
            convert = request.form.get('to_currency')

            #3) Errores en la conversión de monedas:
            error = validarConversion(amount, simbolo, convert)
            if error != None:
                return render_template('purchase.html', form=form, vacio='yes', error=error, monedero=monedero)

            # 4) Finalmente: consulta a la API
            try:
                url = 'https://pro-api.coinmarketcap.com/v1/tools/price-conversion?amount={}&symbol={}&convert={}&CMC_PRO_API_KEY={}'.format(amount, simbolo, convert, API_KEY)
                dicc = peticionAPI(url)

                q_to = dicc['data']['quote'][convert]['price'] # cantidad de monedas que podemos comprar (viene del API)
                precioUnitario = float(amount)/q_to
                fecha_compra = time.strftime("%d/%m/%Y") # fecha y hora del momento de la consulta API
                hora_compra = time.strftime("%X")

                return render_template('purchase.html', vacio='no', form=form, q_to=q_to, precioUnitario=precioUnitario, hora_compra=hora_compra, fecha_compra=fecha_compra, monedero=monedero, amount=amount)
            except Exception as error:
                print("**ERROR**: Conexion url en PURCHASE - {}".format(type(error).__name__), error) # Failed to establish a new connection
                error = "Problema de conexión. Contacte con el administrador."
                return render_template('purchase.html', vacio='yes', form=form, error=error, monedero=monedero)

@app.route('/status')
def status():
    # 1)
    query1 = "SELECT SUM(from_quantity) as eur_from FROM movements WHERE from_currency='EUR';"
    try:
        total_diccionario = consulta(query1)
    except Exception as e:
        print("**ERROR**: Acceso base de datos - {}".format(type(e).__name__))
        mensaje = "Error en acceso a la base de datos. Consulte con el administrador."
        return render_template('movementsList.html', error=mensaje)

    total_eur_invertido = total_diccionario[0]['eur_from']

    #2)
    query2 = 'SELECT sum(case when to_currency = "EUR" then to_quantity else 0 end) - sum(case when  from_currency = "EUR" then from_quantity else 0 end) as saldo_eur from movements;'
    eur_diccionario = consulta(query2)
    saldo_euros_invertidos = eur_diccionario[0]['saldo_eur']

    #3) obtener precio unitario en EUR de todas las criptomonedas:
    simbolo = "BTC,ETH,XRP,LTC,BCH,BNB,USDT,EOS,BSV,XLM,ADA,TRX" # no debe tener espacios en blanco!
    convert = 'EUR'

    url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol={}&convert={}&CMC_PRO_API_KEY={}'.format(simbolo, convert, API_KEY)
    try:
        dicc = peticionAPI(url)
    except Exception as error:
        print("**ERROR**: Conexion url en STATUS - {}".format(type(error).__name__), error)
        error = "Problemas de conexión. Contacte con el administrador."
        return render_template('status.html', invertido=0 , actual=0, error_conexion = error)

    lista_monedas = ['BTC', 'ETH', 'XRP', 'LTC', 'BCH','BNB', 'USDT','EOS','BSV','XLM','ADA','TRX']
    pu_crypto_eur = {}
    id_cryptos = {}
    for moneda in lista_monedas: # crear diccionario pu_crypto_eur
        precio = dicc['data'][moneda]['quote']['EUR']['price']
        id_crypto = dicc['data'][moneda]['id']
        pu_crypto_eur[moneda] = precio
        id_cryptos[moneda] = id_crypto #print(id_cryptos)

    #4)
    monedero = {} # cuantas monedas tengo de cada cripto
    monedero_eur = [] # valor en EUR de las monedas que tengo

    for moneda in lista_monedas:
        query3 = "SELECT sum(case when to_currency = ? then to_quantity else 0 end) - sum(case when  from_currency = ? then from_quantity else 0 end) as saldo_moneda FROM movements;"
        tmp = consulta(query3, (moneda, moneda))
        saldo = tmp[0]['saldo_moneda']

        monedero[moneda] = saldo

        precio_unitario = float(pu_crypto_eur[moneda])
        try:
            monedero_eur.append(saldo * precio_unitario)
        except:
            return render_template('status.html', invertido=0 , actual=0)

    valor_total_cryptos = 0
    for item in monedero_eur:
        valor_total_cryptos += item

    valor_actual = total_eur_invertido + saldo_euros_invertidos + valor_total_cryptos # todo en euros!

    return render_template('status.html', invertido=total_eur_invertido , actual=valor_actual)


from timeit import Timer

REPEATS = 10000

setup = """
values = []
"""  # setup code is only executed once

code_snippets = [
'''
for i in range(10000):
    values.append(i)
values.clear()
''',  # code fragment executed many times
'''
i = 0
while i < 10000:
    values.append(i)
    i += 1
values.clear()
''',  # code fragment executed many times
]

for code_snippet in code_snippets:
    t = Timer(code_snippet, setup)
    print(f"{code_snippet:80.80s}{t.timeit(REPEATS)}")
    print('-' * 60)


import os
import sys

import numpy as np
import pandas as pd
from scipy.stats import pearsonr, spearmanr

from etspredict.prepare_data.prepare_connectomes import load_timeseries
from etspredict.selective_connectomes import ets_amplitudes
from etspredict.timeseries import get_edge_timeseries

def get_subject_rss(subject, session, parcellation, preproc="GS"):
    timeseries = load_timeseries(
        "hcp", subject, parcellation, session, preproc
    )
    ets = get_edge_timeseries(timeseries)

    return ets_amplitudes(ets)

def get_subject_confound(subject, session, fieldname):

    aml_dir = os.path.join(
        "/data", "group", "appliedml", "data", "HCP1200_Confounds_tsv_withFD"
    )
    confounds_file = os.path.join(
        f"{subject}",
        "MNINonLinear",
        "Results",
        f"rfMRI_{session}",
        f"Confounds_{subject}.tsv",
    )
    fd_file = os.path.join(aml_dir, confounds_file)

    return np.array(pd.read_csv(fd_file, sep="\t")[fieldname])

def main(subject, session, parcellation, correlation_method, preproc="GS"):

    fd = get_subject_confound(subject, session, fieldname="FD")
    rss = get_subject_rss(subject, session, parcellation, preproc=preproc)
    gs = get_subject_confound(subject, session, fieldname="GS")

    if correlation_method in ["pearson"]:
        correlation_fd, _ = pearsonr(rss, fd)
        correlation_gs, _ = pearsonr(rss, gs)
    elif correlation_method in ["spearman"]:
        correlation_fd, _ = spearmanr(rss, fd)
        correlation_gs, _ = spearmanr(rss, gs)
    else:
        raise NotImplementedError(f"{correlation_method} not implemented")

    print("correlation done")
    with open(
        f"../results/fd_rss_correlations/"
        f"{subject}_{session}_{parcellation}"
        f"_{preproc}_{correlation_method}.txt",
        "w",
    ) as f:
        f.write(f"{correlation_fd}")

    with open(
        f"../results/gs_rss_correlations/"
        f"{subject}_{session}_{parcellation}"
        f"_{preproc}_{correlation_method}.txt",
        "w",
    ) as f:
        f.write(f"{correlation_gs}")
    print("files saved")

if __name__ == "__main__":

    main(
        subject=sys.argv[1],
        session=sys.argv[2],
        parcellation=sys.argv[3],
        correlation_method=sys.argv[4],
        preproc="GS",
    )

    main(
        subject=sys.argv[1],
        session=sys.argv[2],
        parcellation=sys.argv[3],
        correlation_method=sys.argv[4],
        preproc="no_GS",
    )


import torch
import torch.nn as nn
import torch.optim as optim

import torchvision
import torchvision.transforms as transforms
from torchvision import datasets
from torch.utils.data import DataLoader
from torchvision.utils import save_image

import argparse
import matplotlib
import matplotlib.pyplot as plt

from tqdm import tqdm

import model

matplotlib.style.use('ggplot')

parser = argparse.ArgumentParser()
parser.add_argument('-e', '--epochs', type=int, default=10, help="Number of epoch for VAE to train")
args = parser.parse_args()

epochs = args.epochs
batch_size = 64
lr = 1e-4
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# transform
transform = transforms.Compose([transforms.ToTensor(),])

# train and validation data
train_data = datasets.MNIST(
    root='../data',
    train=True,
    download=True,
    transform=transform
)

val_data = datasets.MNIST(
    root='../data',
    train=False,
    download=True,
    transform=transform
)

# training and validation data loaders
train_loader = DataLoader(
    train_data,
    batch_size=batch_size,
    shuffle=True
)

val_loader = DataLoader(
    val_data,
    batch_size=batch_size,
    shuffle=False
)

model = model.LVAE().to(device)
opt = optim.Adam(model.parameters(), lr=lr)
criterion = nn.BCELoss(reduction='sum')

def final_loss(bce_loss, mu, log_var):
    BCE = bce_loss
    KLD = -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp())
    return BCE + KLD

def fit(model, data_loader):
    model.train()
    running_loss = 0.0
    for i, data in tqdm(enumerate(data_loader)):
        data, _ = data
        data = data.to(device)
        data = data.view(data.size(0), -1)
        opt.zero_grad()
        reconstruction, mu, log_var = model(data)
        bce_loss = criterion(reconstruction, data)
        loss = final_loss(bce_loss, mu, log_var)
        running_loss += loss.item()
        loss.backward()
        opt.step()

    train_loss = running_loss / len(data_loader.dataset)
    return train_loss

def validate(model, data_loader):
    model.eval()
    running_loss = 0.0
    with torch.no_grad():
        for i, data in tqdm(enumerate(data_loader), total=int(len(val_data) / data_loader.batch_size)):
            data, _ = data
            data = data.to(device)
            data = data.view(data.size(0), -1)
            reconstruction, mu, log_var = model(data)
            bce_loss = criterion(reconstruction, data)
            loss = final_loss(bce_loss, mu, log_var)
            running_loss += loss.item()

            # save the last batch input and output of every epoch
            if i == int(len(val_data) / data_loader.batch_size) - 1:
                num_rows = 8
                both = torch.cat((data.view(batch_size, 1, 28, 28)[:8], reconstruction.view(batch_size, 1, 28, 28)[:8]))
                save_image(both.cpu(), f"output/output{epoch}.png", nrow=num_rows)

        val_loss = running_loss / len(data_loader.dataset)
        return val_loss

train_loss = []
val_loss = []

for epoch in range(epochs):
    print(f"Epoch {epoch + 1}/{epochs}")
    train_epoch_loss = fit(model, train_loader)
    val_epoch_loss = validate(model, val_loader)
    train_loss.append(train_epoch_loss)
    val_loss.append(val_epoch_loss)
    print(f"Train Loss: {train_epoch_loss:.4f}, Val Loss: {val_epoch_loss:.4f}")