Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: self service #7136

Merged
merged 7 commits into from
Aug 17, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/assets/v2/css/grants/grant.css
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ background: linear-gradient(85.75deg, #03008D -17.8%, #000000 139.56%); /* W3C,

.grant-partners img {
border-radius: 50px;
width: 3rem;
width: 2rem;
}

.grant-partners .nav-tabs {
Expand Down
3 changes: 2 additions & 1 deletion app/dashboard/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
BountySyncRequest, CoinRedemption, CoinRedemptionRequest, Coupon, Earning, FeedbackEntry, FundRequest,
HackathonEvent, HackathonProject, HackathonRegistration, HackathonSponsor, Interest, Investigation, LabsResearch,
ObjectView, Option, Poll, PollMedia, PortfolioItem, Profile, ProfileVerification, ProfileView, Question,
SearchHistory, Sponsor, Tip, TipPayout, TokenApproval, TribeMember, TribesSubscription, UserAction, UserVerificationModel,
SearchHistory, Sponsor, Tip, TipPayout, TokenApproval, TribeMember, TribesSubscription, UserAction,
UserVerificationModel,
)


Expand Down
33 changes: 24 additions & 9 deletions app/grants/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
from django.conf import settings
from django.contrib import admin
from django.contrib.humanize.templatetags.humanize import naturaltime
from django.shortcuts import redirect
from django.utils import timezone
from django.utils.html import format_html
from django.utils.safestring import mark_safe

from grants.models import CartActivity, CLRMatch, Contribution, Flag, Grant, MatchPledge, PhantomFunding, Subscription
import twitter
from grants.models import (
CartActivity, CLRMatch, Contribution, Flag, Grant, GrantCategory, GrantCLR, GrantType, MatchPledge, PhantomFunding,
Subscription,
)


class GeneralAdmin(admin.ModelAdmin):
Expand All @@ -38,13 +45,10 @@ class FlagAdmin(admin.ModelAdmin):
raw_id_fields = ['profile', 'grant']

def response_change(self, request, obj):
from django.shortcuts import redirect
if "_post_flag" in request.POST:
obj.post_flag()
self.message_user(request, "posted flag to activity feed")
if "_tweet" in request.POST:
import twitter
from django.conf import settings
thelostone-mc marked this conversation as resolved.
Show resolved Hide resolved
# TODO : get @gicoindisputes out of twitter jail
api = twitter.Api(
consumer_key=settings.DISPUTES_TWITTER_CONSUMER_KEY,
Expand Down Expand Up @@ -98,7 +102,7 @@ class GrantAdmin(GeneralAdmin):
'subscriptions_links', 'contributions_links', 'link',
'migrated_to', 'view_count'
]
list_display =['pk', 'sybil_score', 'weighted_risk_score', 'match_amount', 'positive_round_contributor_count', 'is_clr_eligible', 'title', 'active','grant_type', 'link', 'hidden', 'migrated_to']
list_display =['pk', 'sybil_score', 'weighted_risk_score', 'match_amount', 'positive_round_contributor_count', 'is_clr_eligible', 'title', 'active', 'link', 'hidden', 'migrated_to']
raw_id_fields = ['admin_profile']
search_fields = ['description', 'admin_profile__handle']

Expand Down Expand Up @@ -254,7 +258,6 @@ def profile(self, obj):
return format_html(f"<a href='/{obj.subscription.contributor_profile.handle}'>{obj.subscription.contributor_profile}</a>")

def created_on_nt(self, obj):
from django.contrib.humanize.templatetags.humanize import naturaltime
return naturaltime(obj.created_on)

def amount_str(self, obj):
Expand All @@ -273,7 +276,6 @@ def amount(self, obj):
return obj.subscription.amount_per_period

def github_created_on(self, instance):
from django.contrib.humanize.templatetags.humanize import naturaltime
return naturaltime(instance.subscription.contributor_profile.github_created_on)

def from_ip_address(self, instance):
Expand All @@ -298,7 +300,6 @@ def amount_per_period_minus_gas_price(self, instance):
return instance.subscription.amount_per_period_minus_gas_price

def response_change(self, request, obj):
from django.shortcuts import redirect
if "_notify_contribution_failure" in request.POST:
from marketing.mails import grant_txn_failed
grant_txn_failed(obj)
Expand All @@ -320,7 +321,6 @@ class PhantomFundingAdmin(admin.ModelAdmin):
raw_id_fields = ['profile', 'grant']

def github_created_on(self, instance):
from django.contrib.humanize.templatetags.humanize import naturaltime
return naturaltime(instance.profile.github_created_on)

def from_ip_address(self, instance):
Expand All @@ -337,6 +337,18 @@ class CartActivityAdmin(admin.ModelAdmin):
search_fields = ['bulk', 'action', 'grant']


class GrantTypeAdmin(admin.ModelAdmin):
list_display = ['name']


class GrantCategoryAdmin(admin.ModelAdmin):
list_display = ['category']


class GrantCLRAdmin(admin.ModelAdmin):
list_display = ['pk', 'round_num', 'start_date', 'end_date', 'grant_type','is_active']


admin.site.register(PhantomFunding, PhantomFundingAdmin)
admin.site.register(MatchPledge, MatchPledgeAdmin)
admin.site.register(Grant, GrantAdmin)
Expand All @@ -345,3 +357,6 @@ class CartActivityAdmin(admin.ModelAdmin):
admin.site.register(Subscription, SubscriptionAdmin)
admin.site.register(Contribution, ContributionAdmin)
admin.site.register(CartActivity, CartActivityAdmin)
admin.site.register(GrantType, GrantTypeAdmin)
admin.site.register(GrantCategory, GrantCategoryAdmin)
admin.site.register(GrantCLR, GrantCLRAdmin)
119 changes: 28 additions & 91 deletions app/grants/clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,37 +32,8 @@
from marketing.models import Stat
from perftools.models import JSONStore

PREV_CLR_START_DATE = dt.datetime(2020, 3, 23, 12, 0)
PREV_CLR_END_DATE = dt.datetime(2020, 4, 7, 12, 0)
CLR_START_DATE = dt.datetime(2020, 6, 15, 12, 0)
CLR_END_DATE = dt.datetime(2020, 7, 3, 16, 0)

try:
CLR_END_DATE
except NameError:
CLR_END_DATE = timezone.now()

CLR_PERCENTAGE_DISTRIBUTED = 0

# TODO: MOVE TO DB
V_THRESHOLD_TECH = 25.0
V_THRESHOLD_MEDIA = 25.0
V_THRESHOLD_HEALTH = 25.0
V_THRESHOLD_CHANGE = 25.0
V_THRESHOLD_MATIC = 25.0

UV_THRESHOLD_TECH = 5.0
UV_THRESHOLD_MEDIA = 5.0
UV_THRESHOLD_HEALTH = 5.0
UV_THRESHOLD_CHANGE = 5.0
UV_THRESHOLD_MATIC = 5.0

TOTAL_POT_TECH = 100000.0
TOTAL_POT_MEDIA = 50000.0
TOTAL_POT_HEALTH = 0.0
TOTAL_POT_CHANGE = 25000.0
TOTAL_POT_MATIC = 0.0

UV_THRESHOLD = 5.0

'''
translates django grant data structure to a list of lists
Expand Down Expand Up @@ -342,67 +313,28 @@ def calculate_clr_for_donation(grant, amount, grant_contributions_curr, grant_co
Populate Data needed to calculate CLR

Args:
clr_type : media | tech | None
network : mainnet | rinkeby
clr_end_date : datetime
clr_end_date : datetime
network : mainnet | rinkeby
clr_round : GrantCLR
Returns:
contributions : contributions data object
grants : list of grants based on clr_type
phantom_funding_profiles : phantom funding data object
total_pot : total pot for clr_type
v_threshold : verified threshold for clr_type
uv_threshold : unverified threshold for clr_type

'''
def fetch_data(clr_type=None, network='mainnet', clr_start_date=None, clr_end_date=None):
def fetch_data(clr_round, network='mainnet'):

if not clr_start_date:
print('error: fetch_data - missing clr_start_date')
return None, None, None, None
grant_type = clr_round.grant_type

if not clr_end_date:
print('error: fetch_data - missing clr_end_date')
return None, None, None, None
clr_start_date = clr_round.previous_round.start_date if clr_round.previous_round else clr_round.start_date
clr_end_date = clr_round.end_date

contributions = Contribution.objects.prefetch_related('subscription').filter(match=True, created_on__gte=clr_start_date, created_on__lte=clr_end_date, success=True)

if clr_type == 'tech':
grants = Grant.objects.filter(network=network, hidden=False, active=True, grant_type='tech', is_clr_eligible=True, link_to_new_grant=None)
v_threshold = V_THRESHOLD_TECH
uv_threshold = UV_THRESHOLD_TECH
total_pot = TOTAL_POT_TECH

elif clr_type == 'media':
grants = Grant.objects.filter(network=network, hidden=False, active=True, grant_type='media', is_clr_eligible=True, link_to_new_grant=None)
v_threshold = V_THRESHOLD_MEDIA
uv_threshold = UV_THRESHOLD_MEDIA
total_pot = TOTAL_POT_MEDIA

elif clr_type == 'health':
grants = Grant.objects.filter(network=network, hidden=False, active=True, grant_type='health', is_clr_eligible=True, link_to_new_grant=None)
v_threshold = V_THRESHOLD_HEALTH
uv_threshold = UV_THRESHOLD_HEALTH
total_pot = TOTAL_POT_HEALTH

elif clr_type == 'change':
grants = Grant.objects.filter(network=network, hidden=False, active=True, grant_type='change', is_clr_eligible=True, link_to_new_grant=None)
v_threshold = V_THRESHOLD_CHANGE
uv_threshold = UV_THRESHOLD_CHANGE
total_pot = TOTAL_POT_CHANGE

elif clr_type == 'matic':
grants = Grant.objects.filter(network=network, hidden=False, active=True, grant_type='matic', is_clr_eligible=True, link_to_new_grant=None)
v_threshold = V_THRESHOLD_MATIC
uv_threshold = UV_THRESHOLD_MATIC
total_pot = TOTAL_POT_MATIC

else:
return None, None, None, None, None, None
grants = Grant.objects.filter(network=network, hidden=False, active=True, grant_type=grant_type, is_clr_eligible=True, link_to_new_grant=None)

phantom_funding_profiles = PhantomFunding.objects.filter(created_on__gte=clr_start_date, created_on__lte=clr_end_date)

return grants, contributions, phantom_funding_profiles, total_pot, v_threshold, uv_threshold
return grants, contributions, phantom_funding_profiles



Expand All @@ -413,9 +345,7 @@ def fetch_data(clr_type=None, network='mainnet', clr_start_date=None, clr_end_da
grants : grants list
contributions : contributions list for thoe grants
phantom_funding_profiles: phantom funding for those grants
mechanism : verification mechanism (profile_
clr start date : datetime
clr end date : datetime
clr_round : GrantCLR

Returns:
contrib_data_list: {
Expand All @@ -424,17 +354,20 @@ def fetch_data(clr_type=None, network='mainnet', clr_start_date=None, clr_end_da
}

'''
def populate_data_for_clr(grants, contributions, phantom_funding_profiles, mechanism, clr_start_date=None, clr_end_date=None):
def populate_data_for_clr(grants, contributions, phantom_funding_profiles, clr_round):

if not clr_start_date:
print('Error: populate_data_for_clr - missing clr_start_date')
contrib_data_list = []

if not clr_end_date:
print('Error: populate_data_for_clr - missing clr_end_date')
if not clr_round:
print('Error: populate_data_for_clr - missing clr_round')
return contrib_data_list

# set up data to load contributions for each grant
contrib_data_list = []
clr_start_date = clr_round.start_date
clr_end_date = clr_round.end_date

mechanism="profile"

# set up data to load contributions for each grant
for grant in grants:
grant_id = grant.defer_clr_to.pk if grant.defer_clr_to else grant.id

Expand Down Expand Up @@ -478,17 +411,21 @@ def populate_data_for_clr(grants, contributions, phantom_funding_profiles, mecha



def predict_clr(save_to_db=False, from_date=None, clr_type=None, network='mainnet', mechanism='profile'):
def predict_clr(save_to_db=False, from_date=None, clr_round=None, network='mainnet'):
# setup
clr_calc_start_time = timezone.now()
debug_output = []

# one-time data call
grants, contributions, phantom_funding_profiles, total_pot, v_threshold, uv_threshold = fetch_data(clr_type, network, PREV_CLR_START_DATE, CLR_END_DATE)
total_pot = float(clr_round.total_pot)
v_threshold = float(clr_round.threshold)
uv_threshold = UV_THRESHOLD

grants, contributions, phantom_funding_profiles = fetch_data(clr_round, network)

# one for previous, one for current
grant_contributions_curr = populate_data_for_clr(grants, contributions, phantom_funding_profiles, mechanism, CLR_START_DATE, CLR_END_DATE)
grant_contributions_prev = populate_data_for_clr(grants, contributions, phantom_funding_profiles, mechanism, PREV_CLR_START_DATE, PREV_CLR_END_DATE)
grant_contributions_curr = populate_data_for_clr(grants, contributions, phantom_funding_profiles, clr_round)
grant_contributions_prev = populate_data_for_clr(grants, contributions, phantom_funding_profiles, clr_round)

# calculate clr given additional donations
for grant in grants:
Expand Down
62 changes: 31 additions & 31 deletions app/grants/management/commands/estimate_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@

from dashboard.utils import get_tx_status, has_tx_mined
from grants.clr import predict_clr
from grants.models import Contribution, Grant
from grants.views import clr_active
from grants.models import Contribution, Grant, GrantCLR
from marketing.mails import warn_subscription_failed


Expand All @@ -34,37 +33,38 @@ class Command(BaseCommand):
help = 'calculate CLR estimates for all grants'

def add_arguments(self, parser):

parser.add_argument('clr_type', type=str, default='tech', choices=['tech', 'media', 'health', 'change', 'matic'])
parser.add_argument('network', type=str, default='mainnet', choices=['rinkeby', 'mainnet'])
parser.add_argument(
thelostone-mc marked this conversation as resolved.
Show resolved Hide resolved
'-force', '--force', action='store_true', dest='force', default=False, help='Force to run the CLR calcs even if the round is closed'
)
parser.add_argument('clr_pk', type=str, default="all")


def handle(self, *args, **options):
if not clr_active and not options['force']:
print('CLR round is not active according to grants.views.clr_active, so cowardly refusing to spend the CPU cycles + exiting instead')
return

clr_type = options['clr_type']
network = options['network']
# identity mechanism is profiles for traditional rounds. for experimental rounds, where we saw collusion
# make the identity mechanism into funds originated addr
# this is a stopgap until a "one identity mechanism to rule them all is round", probably in round 6.

predict_clr(
save_to_db=True,
from_date=timezone.now(),
clr_type=clr_type,
network=network
)

print("finished CLR estimates")

# TOTAL GRANT
# grants = Grant.objects.filter(network=network, hidden=False, active=True, grant_type=clr_type, link_to_new_grant=None)
# total_clr_distributed = 0
# for grant in grants:
# total_clr_distributed += grant.clr_prediction_curve[0][1]

# print(f'Total CLR allocated for {clr_type} - {total_clr_distributed}')
clr_pk = options['clr_pk']

if clr_pk == "all":
active_clrs_rounds = GrantCLR.objects.filter(is_active=True)
else:
active_clrs_rounds = GrantCLR.objects.filter(pk=clr_pk)

if active_clrs_rounds:
for clr_round in active_clrs_rounds:
print(f"CALCULATING CLR estimates for TYPE: {clr_round.grant_type} | ROUND: {clr_round.round_num}")
predict_clr(
save_to_db=True,
from_date=timezone.now(),
clr_round=clr_round,
network=network
)
print(f"finished CLR estimates for {clr_round.grant_type}")

# TOTAL GRANT
# grants = Grant.objects.filter(network=network, hidden=False, active=True, grant_type=clr_type, link_to_new_grant=None)
# total_clr_distributed = 0
# for grant in grants:
# total_clr_distributed += grant.clr_prediction_curve[0][1]

# print(f'Total CLR allocated for {clr_type} - {total_clr_distributed}')

else:
print("No active CLRs found")
Loading