加了target
This commit is contained in:
parent
ff0a646c81
commit
0a8e6319a4
@ -160,7 +160,15 @@ 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(
|
||||||
|
id='target-input',
|
||||||
|
type='number',
|
||||||
|
placeholder='输入 Target 值',
|
||||||
|
value=None,
|
||||||
|
style={'marginTop': '10px', 'width': '50%'}
|
||||||
|
),
|
||||||
], 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)
|
||||||
])
|
])
|
||||||
return app
|
return app
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import pytz
|
import pytz
|
||||||
from pkg.tool import get_tweets_since_last_friday, format_time_str, get_time_since_last_tweet
|
from pkg.tool import get_tweets_since_last_friday, format_time_str, get_time_since_last_tweet, get_hourly_weighted_array
|
||||||
from pkg.dash.app_init import app
|
from pkg.dash.app_init import app
|
||||||
from dash.dependencies import Input, Output
|
from dash.dependencies import Input, Output
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
@ -9,19 +9,25 @@ 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')]
|
||||||
)
|
)
|
||||||
def update_info(n):
|
def update_info(n, target_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()
|
||||||
_, days_to_next_friday = get_pace_params()
|
tweet_count, days_to_next_friday = get_pace_params()
|
||||||
|
remain_hours = days_to_next_friday * 24
|
||||||
|
now = tweet_count
|
||||||
table_style_border = {'textAlign': 'center', 'border': '1px solid white'}
|
table_style_border = {'textAlign': 'center', 'border': '1px solid white'}
|
||||||
table_style_c = {'textAlign': 'center'}
|
table_style_c = {'textAlign': 'center'}
|
||||||
table_style_l = {'textAlign': 'left'}
|
table_style_l = {'textAlign': 'left'}
|
||||||
|
|
||||||
# First table for Pace
|
target = int(target_value) if target_value is not None else None
|
||||||
|
avg_tweets_per_day = calculate_avg_tweets_per_day(target, now, remain_hours) if target is not None else "未计算"
|
||||||
|
days_passed = 7 - days_to_next_friday
|
||||||
|
avg_tweets = round(tweet_count / days_passed, 2) if days_passed > 0 else 0
|
||||||
|
|
||||||
pace_table_rows = [
|
pace_table_rows = [
|
||||||
html.Tr([
|
html.Tr([
|
||||||
html.Th('Pace', style=table_style_border),
|
html.Th('Pace', style=table_style_border),
|
||||||
@ -66,6 +72,22 @@ def update_info(n):
|
|||||||
html.Td("1.Check Reply",
|
html.Td("1.Check Reply",
|
||||||
colSpan=7,
|
colSpan=7,
|
||||||
style=table_style_l)
|
style=table_style_l)
|
||||||
|
]),
|
||||||
|
html.Tr([
|
||||||
|
html.Td(f"Target: {target if target else '[未设置]'}",
|
||||||
|
colSpan=4,
|
||||||
|
style=table_style_c),
|
||||||
|
html.Td(f"Need's Avg Tweets Per Day: {avg_tweets_per_day}",
|
||||||
|
colSpan=4,
|
||||||
|
style=table_style_l)
|
||||||
|
]),
|
||||||
|
html.Tr([
|
||||||
|
html.Td(f"Avg Tweets: {avg_tweets}",
|
||||||
|
colSpan=4,
|
||||||
|
style=table_style_c),
|
||||||
|
html.Td("", # 右侧留空,与上一行对齐
|
||||||
|
colSpan=4,
|
||||||
|
style=table_style_l)
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
pace_table = html.Table(pace_table_rows, style={
|
pace_table = html.Table(pace_table_rows, style={
|
||||||
@ -114,6 +136,42 @@ def calculate_pace_increase_in_hour():
|
|||||||
new_tweet_count = tweet_count + increment
|
new_tweet_count = tweet_count + increment
|
||||||
new_pace = (new_tweet_count / (7 - future_days)) * future_days + new_tweet_count
|
new_pace = (new_tweet_count / (7 - future_days)) * future_days + new_tweet_count
|
||||||
pace_increase = new_pace - current_pace
|
pace_increase = new_pace - current_pace
|
||||||
# Add current pace to the increase value
|
|
||||||
pace_increases[f'increase_{increment}'] = round(current_pace + pace_increase, 2)
|
pace_increases[f'increase_{increment}'] = round(current_pace + pace_increase, 2)
|
||||||
return pace_increases
|
return pace_increases
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_avg_tweets_per_day(target, now, remain):
|
||||||
|
Xi = get_hourly_weighted_array()
|
||||||
|
if remain <= 0:
|
||||||
|
return "剩余时间不足,无法计算"
|
||||||
|
if target <= now:
|
||||||
|
return "目标已达成,无需额外发帖"
|
||||||
|
|
||||||
|
fx = max(remain - 12, 0)
|
||||||
|
|
||||||
|
if remain > 12:
|
||||||
|
fy = sum(Xi[0:12]) * 24
|
||||||
|
else:
|
||||||
|
full_hours = int(remain)
|
||||||
|
fractional_hour = remain - full_hours
|
||||||
|
if full_hours >= 24:
|
||||||
|
print(f"Debug: full_hours={full_hours} exceeds 24, capping at 23")
|
||||||
|
full_hours = 23
|
||||||
|
fractional_hour = 0 # 如果超过24小时,小数部分忽略
|
||||||
|
|
||||||
|
if full_hours < 0:
|
||||||
|
print(f"Debug: full_hours={full_hours} is negative, setting to 0")
|
||||||
|
full_hours = 0
|
||||||
|
|
||||||
|
if full_hours > 0:
|
||||||
|
fy = sum(Xi[0:full_hours]) + Xi[full_hours] * fractional_hour
|
||||||
|
else:
|
||||||
|
fy = Xi[0] * fractional_hour
|
||||||
|
fy *= 24
|
||||||
|
|
||||||
|
if fx + fy == 0:
|
||||||
|
return "计算无效,请检查剩余时间"
|
||||||
|
|
||||||
|
result = (target - now) / ((fx + fy) / 24)
|
||||||
|
print(f"Debug: fx={fx}, fy={fy}, result={result}")
|
||||||
|
return round(result, 2)
|
@ -112,13 +112,18 @@ def render_tab_content(tab, selected_dates, interval, time_zones, days_to_displa
|
|||||||
|
|
||||||
x_labels = [f"{i * interval:02d}" for i in range(intervals_per_hour)]
|
x_labels = [f"{i * interval:02d}" for i in range(intervals_per_hour)]
|
||||||
|
|
||||||
|
rate_values = [[z_values[h][i] / tweet_count_total if tweet_count_total > 0 else 0
|
||||||
|
for i in range(intervals_per_hour)]
|
||||||
|
for h in range(24)]
|
||||||
|
|
||||||
fig = go.Figure(data=go.Heatmap(
|
fig = go.Figure(data=go.Heatmap(
|
||||||
z=z_values,
|
z=z_values,
|
||||||
x=x_labels,
|
x=x_labels,
|
||||||
y=[f"{h:02d}" for h in hours],
|
y=[f"{h:02d}" for h in hours],
|
||||||
colorscale='Viridis',
|
colorscale='Viridis',
|
||||||
hoverongaps=False,
|
hoverongaps=False,
|
||||||
hovertemplate='%{y}:%{x} EST<br>Tweets: %{z}<extra></extra>'
|
customdata=rate_values,
|
||||||
|
hovertemplate='%{y}:%{x} EST<br>Tweets: %{z}<br>Rate: %{customdata:.2%}<extra></extra>'
|
||||||
))
|
))
|
||||||
|
|
||||||
if tab in ['line', 'one_day_heatmap']:
|
if tab in ['line', 'one_day_heatmap']:
|
||||||
|
30
pkg/tool.py
30
pkg/tool.py
@ -95,3 +95,33 @@ def format_time_str(days_to_next_friday):
|
|||||||
seconds = int(total_seconds % 60)
|
seconds = int(total_seconds % 60)
|
||||||
total_hours = round(days_to_next_friday * 24, 2)
|
total_hours = round(days_to_next_friday * 24, 2)
|
||||||
return f"{days}d {hours:02d}h {minutes:02d}m {seconds:02d}s ({total_hours}h)"
|
return f"{days}d {hours:02d}h {minutes:02d}m {seconds:02d}s ({total_hours}h)"
|
||||||
|
|
||||||
|
|
||||||
|
def get_hourly_weighted_array():
|
||||||
|
est = pytz.timezone('US/Eastern')
|
||||||
|
now = datetime.now(est).date()
|
||||||
|
last_7_days = [now - timedelta(days=i) for i in range(7)]
|
||||||
|
|
||||||
|
multi_data_agg = render_data.global_agg_df[
|
||||||
|
render_data.global_agg_df['date'].isin(last_7_days)].copy()
|
||||||
|
|
||||||
|
if multi_data_agg.empty:
|
||||||
|
return [1 / 24] * 24
|
||||||
|
|
||||||
|
agg_data = aggregate_data(multi_data_agg, 60)
|
||||||
|
one_day_data = agg_data.groupby('interval_group')['tweet_count'].sum().reset_index()
|
||||||
|
tweet_count_total = one_day_data['tweet_count'].sum()
|
||||||
|
|
||||||
|
hourly_rates = [0] * 24
|
||||||
|
for _, row in one_day_data.iterrows():
|
||||||
|
minute = row['interval_group']
|
||||||
|
hour = int(minute // 60)
|
||||||
|
if hour < 24:
|
||||||
|
hourly_rates[hour] = row['tweet_count'] / tweet_count_total if tweet_count_total > 0 else 0
|
||||||
|
|
||||||
|
total_rate = sum(hourly_rates)
|
||||||
|
if total_rate > 0:
|
||||||
|
hourly_rates = [rate / total_rate for rate in hourly_rates]
|
||||||
|
else:
|
||||||
|
hourly_rates = [1 / 24] * 24
|
||||||
|
return hourly_rates
|
Loading…
x
Reference in New Issue
Block a user