+可调节的prediction tweets以及Pace
This commit is contained in:
parent
74a0efc324
commit
5a30d6f20f
@ -3,9 +3,7 @@ from pkg.config import interval_options, days_options, render_data
|
|||||||
|
|
||||||
|
|
||||||
def layout_config(app):
|
def layout_config(app):
|
||||||
# Dash app layout (unchanged except default days value)
|
|
||||||
app.layout = html.Div([
|
app.layout = html.Div([
|
||||||
# Left sidebar with clock button and tooltip (unchanged)
|
|
||||||
html.Div(
|
html.Div(
|
||||||
id='clock-container',
|
id='clock-container',
|
||||||
children=[
|
children=[
|
||||||
@ -63,7 +61,6 @@ def layout_config(app):
|
|||||||
'whiteSpace': 'nowrap'
|
'whiteSpace': 'nowrap'
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
# 新增按钮和提示框
|
|
||||||
html.Div(
|
html.Div(
|
||||||
id='info-button',
|
id='info-button',
|
||||||
children='ℹ️',
|
children='ℹ️',
|
||||||
@ -76,11 +73,11 @@ def layout_config(app):
|
|||||||
),
|
),
|
||||||
html.Div(
|
html.Div(
|
||||||
id='info-tooltip',
|
id='info-tooltip',
|
||||||
children='这是一个信息按钮示例', # 默认显示的信息
|
children='这是一个信息按钮示例',
|
||||||
style={
|
style={
|
||||||
'position': 'absolute',
|
'position': 'absolute',
|
||||||
'left': '35px',
|
'left': '35px',
|
||||||
'top': '80px', # 调整位置,避免与其他 tooltip 重叠
|
'top': '80px',
|
||||||
'backgroundColor': 'rgba(0, 0, 0, 0.8)',
|
'backgroundColor': 'rgba(0, 0, 0, 0.8)',
|
||||||
'color': 'white',
|
'color': 'white',
|
||||||
'padding': '10px',
|
'padding': '10px',
|
||||||
@ -97,7 +94,7 @@ def layout_config(app):
|
|||||||
html.Img(
|
html.Img(
|
||||||
src='https://pbs.twimg.com/profile_images/1893803697185910784/Na5lOWi5_400x400.jpg',
|
src='https://pbs.twimg.com/profile_images/1893803697185910784/Na5lOWi5_400x400.jpg',
|
||||||
style={
|
style={
|
||||||
'height': '24px', # Matches fontSize of other buttons
|
'height': '24px',
|
||||||
'width': '24px',
|
'width': '24px',
|
||||||
'cursor': 'pointer',
|
'cursor': 'pointer',
|
||||||
'padding': '5px',
|
'padding': '5px',
|
||||||
@ -139,7 +136,7 @@ def layout_config(app):
|
|||||||
dcc.Dropdown(
|
dcc.Dropdown(
|
||||||
id='days-display-picker',
|
id='days-display-picker',
|
||||||
options=days_options,
|
options=days_options,
|
||||||
value=30, # Default changed to 30 since 1 is removed
|
value=30,
|
||||||
style={'width': '50%', 'marginTop': '10px'}
|
style={'width': '50%', 'marginTop': '10px'}
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
@ -160,13 +157,48 @@ def layout_config(app):
|
|||||||
dcc.Tab(label='Heatmap(1-day)', value='one_day_heatmap'),
|
dcc.Tab(label='Heatmap(1-day)', value='one_day_heatmap'),
|
||||||
]),
|
]),
|
||||||
html.Div(id='tabs-content'),
|
html.Div(id='tabs-content'),
|
||||||
dcc.Input(
|
html.Table([
|
||||||
id='target-input',
|
html.Tr([
|
||||||
type='number',
|
html.Td("Target:", style={'paddingRight': '10px'}),
|
||||||
placeholder='输入 Target 值',
|
html.Td(
|
||||||
value=None,
|
dcc.Input(
|
||||||
style={'marginTop': '10px', 'width': '50%'}
|
id='target-input',
|
||||||
),
|
type='number',
|
||||||
|
placeholder='输入 Target 值',
|
||||||
|
value=None,
|
||||||
|
style={'width': '100%'}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
html.Tr([
|
||||||
|
html.Td("Predict Tweets:", style={'paddingRight': '10px'}),
|
||||||
|
html.Td(
|
||||||
|
dcc.Input(
|
||||||
|
id='predict-tweets-input',
|
||||||
|
type='number',
|
||||||
|
placeholder='输入 Predict Tweets 值',
|
||||||
|
value=None,
|
||||||
|
style={'width': '100%'}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
html.Tr([
|
||||||
|
html.Td("Hour:", style={'paddingRight': '10px'}),
|
||||||
|
html.Td(
|
||||||
|
dcc.Input(
|
||||||
|
id='hour-input',
|
||||||
|
type='number',
|
||||||
|
placeholder='输入 Hour 值',
|
||||||
|
value=None,
|
||||||
|
style={'width': '100%'}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
])
|
||||||
|
], style={
|
||||||
|
'width': '50%',
|
||||||
|
'marginTop': '10px',
|
||||||
|
'borderCollapse': 'collapse'
|
||||||
|
})
|
||||||
], style={'marginLeft': '50px'}),
|
], style={'marginLeft': '50px'}),
|
||||||
|
|
||||||
dcc.Interval(id='clock-interval', interval=1000, n_intervals=0)
|
dcc.Interval(id='clock-interval', interval=1000, n_intervals=0)
|
||||||
|
@ -10,12 +10,14 @@ from dash import html
|
|||||||
@app.callback(
|
@app.callback(
|
||||||
[Output('info-tooltip', 'children')],
|
[Output('info-tooltip', 'children')],
|
||||||
[Input('clock-interval', 'n_intervals'),
|
[Input('clock-interval', 'n_intervals'),
|
||||||
Input('target-input', 'value')]
|
Input('target-input', 'value'),
|
||||||
|
Input('predict-tweets-input', 'value'),
|
||||||
|
Input('hour-input', 'value')]
|
||||||
)
|
)
|
||||||
def update_info(n, target_value):
|
def update_info(n, target_value, increment_value, hour_value):
|
||||||
pace = calculate_tweet_pace()
|
pace = calculate_tweet_pace()
|
||||||
decline_rates = calculate_pace_decline_rate()
|
decline_rates = calculate_pace_decline_rate()
|
||||||
pace_increases = calculate_pace_increase_in_hour()
|
pace_increases = calculate_pace_increase_in_hour(increment_value, hour_value)
|
||||||
tweet_count, days_to_next_friday = get_pace_params()
|
tweet_count, days_to_next_friday = get_pace_params()
|
||||||
remain_hours = days_to_next_friday * 24
|
remain_hours = days_to_next_friday * 24
|
||||||
now = tweet_count
|
now = tweet_count
|
||||||
@ -28,6 +30,16 @@ def update_info(n, target_value):
|
|||||||
days_passed = 7 - days_to_next_friday
|
days_passed = 7 - days_to_next_friday
|
||||||
avg_tweets = round(tweet_count / days_passed, 2) if days_passed > 0 else 0
|
avg_tweets = round(tweet_count / days_passed, 2) if days_passed > 0 else 0
|
||||||
|
|
||||||
|
custom_increment = pace_increases.get('custom_increment')
|
||||||
|
if custom_increment is None:
|
||||||
|
custom_header = "[TBD]"
|
||||||
|
custom_value = "TBD"
|
||||||
|
else:
|
||||||
|
increment = pace_increases['custom_increment_key']
|
||||||
|
hours = int(hour_value)
|
||||||
|
custom_header = f"{increment}({hours}h)"
|
||||||
|
custom_value = f"{custom_increment:.2f}"
|
||||||
|
|
||||||
pace_table_rows = [
|
pace_table_rows = [
|
||||||
html.Tr([
|
html.Tr([
|
||||||
html.Th('Pace', style=table_style_border),
|
html.Th('Pace', style=table_style_border),
|
||||||
@ -37,7 +49,7 @@ def update_info(n, target_value):
|
|||||||
html.Th('5(1h)', style=table_style_border),
|
html.Th('5(1h)', style=table_style_border),
|
||||||
html.Th('10(1h)', style=table_style_border),
|
html.Th('10(1h)', style=table_style_border),
|
||||||
html.Th('20(1h)', style=table_style_border),
|
html.Th('20(1h)', style=table_style_border),
|
||||||
html.Th('30(1h)', style=table_style_border)
|
html.Th(custom_header, style=table_style_border)
|
||||||
]),
|
]),
|
||||||
html.Tr([
|
html.Tr([
|
||||||
html.Td(f"{pace:.2f}", style=table_style_border),
|
html.Td(f"{pace:.2f}", style=table_style_border),
|
||||||
@ -47,23 +59,15 @@ def update_info(n, target_value):
|
|||||||
html.Td(f"{pace_increases['increase_5']:.2f}", style=table_style_border),
|
html.Td(f"{pace_increases['increase_5']:.2f}", style=table_style_border),
|
||||||
html.Td(f"{pace_increases['increase_10']:.2f}", style=table_style_border),
|
html.Td(f"{pace_increases['increase_10']:.2f}", style=table_style_border),
|
||||||
html.Td(f"{pace_increases['increase_20']:.2f}", style=table_style_border),
|
html.Td(f"{pace_increases['increase_20']:.2f}", style=table_style_border),
|
||||||
html.Td(f"{pace_increases['increase_30']:.2f}", style=table_style_border)
|
html.Td(custom_value, style=table_style_border)
|
||||||
]),
|
]),
|
||||||
html.Tr([
|
html.Tr([
|
||||||
html.Td(f"Remain",
|
html.Td(f"Remain", colSpan=4, style=table_style_c),
|
||||||
colSpan=4,
|
html.Td(format_time_str(days_to_next_friday), colSpan=4, style=table_style_l)
|
||||||
style=table_style_c),
|
|
||||||
html.Td(format_time_str(days_to_next_friday),
|
|
||||||
colSpan=4,
|
|
||||||
style=table_style_l)
|
|
||||||
]),
|
]),
|
||||||
html.Tr([
|
html.Tr([
|
||||||
html.Td(f"Last Tweet",
|
html.Td(f"Last Tweet", colSpan=4, style=table_style_c),
|
||||||
colSpan=4,
|
html.Td(format_time_str(get_time_since_last_tweet()), colSpan=4, style=table_style_l)
|
||||||
style=table_style_c),
|
|
||||||
html.Td(format_time_str(get_time_since_last_tweet()),
|
|
||||||
colSpan=4,
|
|
||||||
style=table_style_l)
|
|
||||||
]),
|
]),
|
||||||
html.Tr([
|
html.Tr([
|
||||||
html.Th("Target", colSpan=2, style=table_style_border),
|
html.Th("Target", colSpan=2, style=table_style_border),
|
||||||
@ -83,7 +87,6 @@ def update_info(n, target_value):
|
|||||||
})
|
})
|
||||||
return [pace_table]
|
return [pace_table]
|
||||||
|
|
||||||
|
|
||||||
def get_pace_params():
|
def get_pace_params():
|
||||||
est = pytz.timezone('US/Eastern')
|
est = pytz.timezone('US/Eastern')
|
||||||
now = datetime.now(est)
|
now = datetime.now(est)
|
||||||
@ -112,20 +115,35 @@ def calculate_pace_decline_rate():
|
|||||||
return round(decline_per_hour, 2)
|
return round(decline_per_hour, 2)
|
||||||
|
|
||||||
|
|
||||||
def calculate_pace_increase_in_hour():
|
def calculate_pace_for_increment(increment, hours, tweet_count, days_to_next_friday, current_pace):
|
||||||
|
future_days = days_to_next_friday - (hours / 24)
|
||||||
|
new_tweet_count = tweet_count + increment
|
||||||
|
if future_days <= 0:
|
||||||
|
return round(new_tweet_count, 2)
|
||||||
|
new_pace = (new_tweet_count / (7 - future_days)) * future_days + new_tweet_count
|
||||||
|
return round(max(new_pace, new_tweet_count), 2)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_pace_increase_in_hour(increment_value, hour_value):
|
||||||
tweet_count, days_to_next_friday = get_pace_params()
|
tweet_count, days_to_next_friday = get_pace_params()
|
||||||
current_pace = (tweet_count / (7 - days_to_next_friday)) * days_to_next_friday + tweet_count
|
current_pace = (tweet_count / (7 - days_to_next_friday)) * days_to_next_friday + tweet_count
|
||||||
future_days = days_to_next_friday - (1 / 24)
|
increments = [0, 1, 5, 10, 20]
|
||||||
increments = [0, 1, 5, 10, 20, 30]
|
|
||||||
pace_increases = {}
|
pace_increases = {}
|
||||||
for increment in increments:
|
for inc in increments:
|
||||||
new_tweet_count = tweet_count + increment
|
pace_increases[f'increase_{inc}'] = calculate_pace_for_increment(
|
||||||
new_pace = (new_tweet_count / (7 - future_days)) * future_days + new_tweet_count
|
inc, 1, tweet_count, days_to_next_friday, current_pace
|
||||||
pace_increase = new_pace - current_pace
|
)
|
||||||
pace_increases[f'increase_{increment}'] = round(current_pace + pace_increase, 2)
|
if increment_value is None or hour_value is None:
|
||||||
|
pace_increases['custom_increment'] = None
|
||||||
|
else:
|
||||||
|
increment = int(increment_value)
|
||||||
|
hours = int(hour_value)
|
||||||
|
pace_increases['custom_increment'] = calculate_pace_for_increment(
|
||||||
|
increment, hours, tweet_count, days_to_next_friday, current_pace
|
||||||
|
)
|
||||||
|
pace_increases['custom_increment_key'] = increment
|
||||||
return pace_increases
|
return pace_increases
|
||||||
|
|
||||||
|
|
||||||
def calculate_avg_tweets_per_day(target, now, remain):
|
def calculate_avg_tweets_per_day(target, now, remain):
|
||||||
Xi = get_hourly_weighted_array()
|
Xi = get_hourly_weighted_array()
|
||||||
if remain <= 0:
|
if remain <= 0:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user