ADD file via upload

This commit is contained in:
floraachy 2025-03-20 08:37:45 +08:00
parent 8f056f3778
commit 330d874939
1 changed files with 611 additions and 0 deletions

611
views.py Normal file
View File

@ -0,0 +1,611 @@
import configparser
import math
import requests
import json
import os
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from maturityAnalyse import settings
config_file_path = os.path.join(settings.BASE_DIR, 'static', 'config.ini')
# 加载配置文件
def load_config(file_path):
config = configparser.ConfigParser()
config.read(file_path)
return config['Limits']
# 获取最大最小值
def get_extreme_values(name):
limits = load_config(config_file_path)
try:
max_value = int(limits[f"{name}_max"])
min_value = int(limits[f"{name}_min"])
except KeyError:
print(f"没有找到配置项: {name}")
max_value, min_value = None, None
return max_value, min_value
# 获取成熟度计算所需的上下文(最大最小值)
def get_maturity_context():
context = MaturityContext()
context.commits_number_max, context.commits_number_min = get_extreme_values("commits_number")
context.contributing_max, context.contributing_min = get_extreme_values("contributing")
context.critical_advisory_max, context.critical_advisory_min = get_extreme_values("critical_advisory")
context.forks_max, context.forks_min = get_extreme_values("forks")
context.high_advisory_max, context.high_advisory_min = get_extreme_values("high_advisory")
context.issue_closed_max, context.issue_closed_min = get_extreme_values("issue_closed")
context.issue_opened_max, context.issue_opened_min = get_extreme_values("issue_opened")
context.license_max, context.license_min = get_extreme_values("license_info")
context.low_advisory_max, context.low_advisory_min = get_extreme_values("low_advisory")
context.moderate_advisory_max, context.moderate_advisory_min = get_extreme_values("moderate_advisory")
context.stars_max, context.stars_min = get_extreme_values("stars")
context.release_number_max, context.release_number_min = get_extreme_values("release_number")
context.developer_number_max, context.developer_number_min = get_extreme_values("developer_number")
return context
class MaturityContext:
def __init__(self):
self.stars_max = 0
self.stars_min = 0
self.watching_max = 0
self.watching_min = 0
self.forks_max = 0
self.forks_min = 0
self.commits_number_max = 0
self.commits_number_min = 0
self.license_max = 0
self.license_min = 0
self.issue_closed_max = 0
self.issue_closed_min = 0
self.issue_opened_max = 0
self.issue_opened_min = 0
self.low_advisory_max = 0
self.low_advisory_min = 0
self.moderate_advisory_max = 0
self.moderate_advisory_min = 0
self.high_advisory_max = 0
self.high_advisory_min = 0
self.critical_advisory_max = 0
self.critical_advisory_min = 0
self.contributing_max = 0
self.contributing_min = 0
self.developer_number_max = 0
self.developer_number_min = 0
self.release_number_max = 0
self.release_number_min = 0
class Software:
def __init__(self, license, issue_opened, issue_closed, low_advisory, moderate_advisory, high_advisory,
critical_advisory, stars, watching, forks, commits_number, average_day_interval, readme,
contributing, developer_number, release_number, user_number, sum_user_score):
self.license = license
self.issue_opened = issue_opened
self.issue_closed = issue_closed
self.low_advisory = low_advisory
self.moderate_advisory = moderate_advisory
self.high_advisory = high_advisory
self.critical_advisory = critical_advisory
self.stars = stars
self.watching = watching
self.forks = forks
self.commits_number = commits_number
self.contributing = contributing
self.developer_number = developer_number
self.release_number = release_number
class AllWeightSoftware:
def __init__(self, software):
self.s = software
self.m = 0
def generate_score(value, max_value, min_value):
if max_value - min_value == 0:
return 100 if value > 0 else 0
if max_value > 2:
return log_generate_score(value, max_value, min_value)
else:
return normal_generate_score(value, max_value, min_value)
def normal_generate_score(value, max_value, min_value):
return int(100 * (value - min_value) / (max_value - min_value))
def log_generate_score(value, max_value, min_value):
if max_value - min_value == 0 and max_value != 0:
return 50
fv = math.log10(value) if value > 0 else 0
fmax = math.log10(max_value) if max_value != 0 else 0
fmin = math.log10(min_value) if min_value != 0 else 0
return int(100 * (fv - fmin) / (fmax - fmin))
def maturity(software, context):
ws = AllWeightSoftware(software)
# 计算每个属性的分数
ws.license_score = generate_score(software.license, context.license_max, context.license_min)
ws.open_issue_score = generate_score(software.issue_opened, context.issue_opened_max,
context.issue_opened_min)
ws.closed_issue_score = generate_score(software.issue_closed, context.issue_closed_max, context.issue_closed_min)
ws.low_advisory_score = 100 - generate_score(software.low_advisory, context.low_advisory_max,
context.low_advisory_min)
ws.moderate_advisory_score = 100 - generate_score(software.moderate_advisory, context.moderate_advisory_max,
context.moderate_advisory_min)
ws.high_advisory_score = 100 - generate_score(software.high_advisory, context.high_advisory_max,
context.high_advisory_min)
ws.critical_advisory_score = 100 - generate_score(software.critical_advisory, context.critical_advisory_max,
context.critical_advisory_min)
ws.stars_score = generate_score(software.stars, context.stars_max, context.stars_min)
ws.watching_score = generate_score(software.watching, context.watching_max, context.watching_min)
ws.fork_score = generate_score(software.forks, context.forks_max, context.forks_min)
ws.commits_number_score = generate_score(software.commits_number, context.commits_number_max,
context.commits_number_min)
ws.developer_number_score = generate_score(software.developer_number, context.developer_number_max,
context.developer_number_min)
ws.release_number_score = generate_score(software.release_number, context.release_number_max,
context.release_number_min)
# 计算整体成熟度,去掉权重影响
ws.m = (ws.license_score + ws.open_issue_score + ws.closed_issue_score +
# 降低了这部分内容的权重
(ws.low_advisory_score + ws.moderate_advisory_score + ws.high_advisory_score + ws.critical_advisory_score) * 0.25 +
ws.stars_score + ws.watching_score + ws.fork_score + ws.commits_number_score +
ws.developer_number_score + ws.release_number_score) / 10
stage = 0
if ws.m < 60:
stage = 2
elif ws.m >= 60 and ws.m < 80:
stage = 1
yadd = stage * 3 - 1
scores_charts = [
{
"name": "license_score",
"score": ws.license_score,
"description": "开源许可证评分",
"criteria": {
"100": "使用标准开源许可证(MIT/Apache/GPL等)",
"0": "无许可证"
},
"suggestion": "建议使用标准的开源许可证以明确项目的使用条款和限制",
"itemStyle": {
"color": "#e9ff40"
},
"value": [
3,
1 + yadd,
ws.license_score
]
},
{
"name": "open_issue_score",
"score": ws.open_issue_score,
"description": "未解决issue评分",
"criteria": {
"80-100": "未解决issue较少",
"60-80": "未解决issue较多",
"0-60": "未解决issue很多"
},
"suggestion": "保持适度的未解决issue数量,及时处理重要issue",
"itemStyle": {
"color": "#abd9e9"
},
"value": [
7,
2 + yadd,
ws.open_issue_score
]
},
{
"name": "closed_issue_score",
"score": ws.closed_issue_score,
"description": "已解决issue评分",
"criteria": {
"80-100": "已解决issue很多",
"60-80": "已解决issue较多",
"0-60": "已解决issue较少"
},
"suggestion": "提高issue解决率,保持良好的问题跟踪和处理机制",
"itemStyle": {
"color": "#74add1"
},
"value": [
8,
2 + yadd,
ws.closed_issue_score
]
},
{
"name": "low_advisory_score",
"score": ws.low_advisory_score,
"description": "低风险安全警告评分",
"criteria": {
"100": "无低风险警告",
"0": "多个低风险警告"
},
"suggestion": "定期检查并修复安全隐患,即使是低风险问题也应重视",
"itemStyle": {
"color": "#ffffbf"
},
"value": [
0,
1 + yadd,
ws.low_advisory_score
]
},
{
"name": "moderate_advisory_score",
"score": ws.moderate_advisory_score,
"description": "中等风险安全警告评分",
"criteria": {
"100": "无中等风险警告",
"0": "多个中风险警告"
},
"suggestion": "优先处理中等风险安全问题,避免安全隐患扩大",
"itemStyle": {
"color": "#fee090"
},
"value": [
0,
2 + yadd,
ws.moderate_advisory_score
]
},
{
"name": "high_advisory_score",
"score": ws.high_advisory_score,
"description": "高风险安全警告评分",
"criteria": {
"100": "无高风险警告",
"0": "多个高风险警告"
},
"suggestion": "高风险安全问题必须立即处理,可考虑发布安全补丁版本",
"itemStyle": {
"color": "#fdae61"
},
"value": [
1,
1 + yadd,
ws.high_advisory_score
]
},
{
"name": "critical_advisory_score",
"score": ws.critical_advisory_score,
"description": "严重风险安全警告评分",
"criteria": {
"100": "无严重风险警告",
"0": "多个严重风险警告"
},
"suggestion": "严重安全问题需要紧急修复并及时通知用户更新",
"itemStyle": {
"color": "#f46d43"
},
"value": [
1,
2 + yadd,
ws.critical_advisory_score
]
},
{
"name": "stars_score",
"score": ws.stars_score,
"description": "项目Star数评分",
"criteria": {
"80-100": "Star很多",
"60-80": "Star较多",
"0-60": "Star较少"
},
"suggestion": "提高项目影响力,完善文档和功能以吸引更多用户关注",
"itemStyle": {
"color": "#93AAFC"
},
"value": [
3,
2 + yadd,
ws.stars_score
]
},
{
"name": "watching_score",
"score": ws.watching_score,
"description": "项目关注者评分",
"criteria": {
"80-100": "关注者很多",
"60-80": "关注者较多",
"0-60": "关注者较少"
},
"suggestion": "增加项目曝光度,保持更新以维持用户关注度",
"itemStyle": {
"color": "#40daff"
},
"value": [
4,
2 + yadd,
ws.watching_score
]
},
{
"name": "fork_score",
"score": ws.fork_score,
"description": "项目fork数评分",
"criteria": {
"80-100": "fork数很多",
"60-80": "fork数较多",
"0-60": "fork数较少"
},
"suggestion": "鼓励社区贡献,完善协作指南以促进fork开发",
"itemStyle": {
"color": "#73d797"
},
"value": [
5,
1 + yadd,
ws.fork_score
]
},
{
"name": "commits_number_score",
"score": ws.commits_number_score,
"description": "提交次数评分",
"criteria": {
"80-100": "提交次数很多",
"60-80": "提交次数较多",
"0-60": "提交次数较少"
},
"suggestion": "保持稳定的开发活跃度,定期提交代码更新",
"itemStyle": {
"color": "#ad73d7"
},
"value": [
6,
1 + yadd,
ws.commits_number_score
]
},
{
"name": "developer_number_score",
"score": ws.developer_number_score,
"description": "开发者数量评分",
"criteria": {
"80-100": "开发者数量很多",
"60-80": "开发者数量较多",
"0-60": "开发者数量较少"
},
"suggestion": "扩大开发团队,培养核心贡献者",
"itemStyle": {
"color": "#ee6df5"
},
"value": [
2,
2 + yadd,
ws.developer_number_score
]
},
{
"name": "release_number_score",
"score": ws.release_number_score,
"description": "发布版本数评分",
"criteria": {
"80-100": "发布版本数很多",
"60-80": "发布版本数较多",
"0-60": "发布版本数较少"
},
"suggestion": "建立规范的版本发布流程,保持稳定的迭代节奏",
"itemStyle": {
"color": "#c4b7e5"
},
"value": [
2,
1 + yadd,
ws.release_number_score
]
},
]
main_score = {
"name": "overall_maturity_score",
"score": ws.m,
"description": "总体成熟度评分",
"criteria": {
"80-100": "项目成熟,维护良好",
"60-80": "项目稳定,有待改进",
"40-60": "项目基本可用,需要加强维护",
"0-40": "项目初期或疏于维护"
},
"x_axis": ["稳健性","稳健性","稳健性","扩展性","扩展性","扩展性","维护性","维护性","维护性"],
"y_axis": ["成熟型","成熟型","成熟型","稳定型","稳定型","稳定型","成长型","成长型","成长型"],
"suggestion": "根据各项分值改进薄弱环节,提高项目整体质量"
}
return {'main_score': main_score, 'scores': scores_charts}
def fetch_data(url):
"""从给定 URL 获取数据并以 JSON 格式返回。"""
response = requests.get(url)
response.raise_for_status() # 对于错误响应抛出异常
return response.json()
@require_http_methods(['GET'])
def calculate(request):
owner = request.GET.get('owner')
repository = request.GET.get('repository')
env_url = "https://www.gitlink.org.cn"
if request.GET.get('env_url') == "testforgeplus":
env_url = "https://testforgeplus.trustie.net"
# owner = "xuos" # 替换为实际的 owner
# repository = "xiuos" # 替换为实际的 repository
# owner = "leslieder"
# repository = "nodom"
# owner = "openEuler-Ecosystem"
# repository = "openEuler-EulerOS"
# 从 API 获取数据
link1_info = f"{env_url}/api/{owner}/{repository}/detail.json"
link2_contri = f"{env_url}/api/{owner}/{repository}/contributors.json"
link3_issue = f"{env_url}/api/{owner}/{repository}/issues.json"
link4_commits = f"{env_url}/api/{owner}/{repository}/commits.json"
link_release = f"{env_url}/api/{owner}/{repository}/releases.json"
try:
software_detail = fetch_data(link1_info)
contributors = fetch_data(link2_contri)
issues = fetch_data(link3_issue)
commits = fetch_data(link4_commits)
releases = fetch_data(link_release)
# 提取必要的信息
license_info = 1 if software_detail.get("license_name") else 0
issue_opened = issues.get("open_count", 0)
issue_closed = issues.get("close_count", 0)
low_advisory = software_detail.get("advisories", {}).get("low", 0)
moderate_advisory = software_detail.get("advisories", {}).get("moderate", 0)
high_advisory = software_detail.get("advisories", {}).get("high", 0)
critical_advisory = software_detail.get("advisories", {}).get("critical", 0)
stars = software_detail.get("praises_count", 0)
watching = software_detail.get("watchers_count", 0)
forks = software_detail.get("forked_count", 0)
commits_number = commits.get("total_count")
average_day_interval = software_detail.get("average_day_interval", 0)
readme = software_detail.get("readme", False)
contributing = software_detail.get("contributing", False)
developer_number = len(contributors.get("list"))
release_number = releases.get("total_count")
user_number = software_detail.get("user_number", 0)
sum_user_score = software_detail.get("sum_user_score", 0)
except TypeError:
return JsonResponse({'data': {}})
except:
return JsonResponse({'data': {}})
# 输出每个信息
# print("许可证:", license_info)
# print("打开的问题数量:", issue_opened)
# print("关闭的问题数量:", issue_closed)
# print("低风险通报数量:", low_advisory)
# print("中风险通报数量:", moderate_advisory)
# print("高风险通报数量:", high_advisory)
# print("严重风险通报数量:", critical_advisory)
# print("星级:", stars)
# print("关注者数量:", watching)
# print("分支数量:", forks)
# print("提交数量:", commits_number)
# print("平均天数间隔:", average_day_interval)
# print("是否包含 README:", readme)
# print("是否包含贡献指南:", contributing)
# print("开发者数量:", developer_number)
# print("发布版本数量:", release_number)
# print("用户数量:", user_number)
# print("用户总评分:", sum_user_score)
# 创建 Software 实例
software = Software(
license=license_info,
issue_opened=issue_opened,
issue_closed=issue_closed,
low_advisory=low_advisory,
moderate_advisory=moderate_advisory,
high_advisory=high_advisory,
critical_advisory=critical_advisory,
stars=stars,
watching=watching,
forks=forks,
commits_number=commits_number,
average_day_interval=average_day_interval,
readme=readme,
contributing=contributing,
developer_number=developer_number,
release_number=release_number,
user_number=user_number,
sum_user_score=sum_user_score
)
update_config(software)
context = get_maturity_context()
maturity_score = maturity(software, context)
return JsonResponse({'data': maturity_score})
def update_config(software):
"""根据软件数据更新 config.ini 文件"""
config = configparser.ConfigParser()
config.read(config_file_path)
# 更新每个数据项
update_config_value(config, 'license_info', software.license)
update_config_value(config, 'issue_opened', software.issue_opened)
update_config_value(config, 'issue_closed', software.issue_closed)
update_config_value(config, 'low_advisory', software.low_advisory)
update_config_value(config, 'moderate_advisory', software.moderate_advisory)
update_config_value(config, 'high_advisory', software.high_advisory)
update_config_value(config, 'critical_advisory', software.critical_advisory)
update_config_value(config, 'stars', software.stars)
update_config_value(config, 'watching', software.watching)
update_config_value(config, 'forks', software.forks)
update_config_value(config, 'commits_number', software.commits_number)
update_config_value(config, 'developer_number', software.developer_number)
update_config_value(config, 'release_number', software.release_number)
# 保存更新后的配置
with open(config_file_path, 'w') as configfile:
config.write(configfile)
def update_config_value(config, key, value):
"""更新配置中的最大值和最小值"""
section = 'Limits' # 指定使用的节
# 获取当前最小值和最大值
current_min = config.getint(section, key + '_min')
current_max = config.getint(section, key + '_max')
# 更新最小值
if value < current_min:
config.set(section, key + '_min', str(value))
# 更新最大值
if value > current_max:
config.set(section, key + '_max', str(value))
# if __name__ == "__main__":
# owner = "xuos" # 替换为实际的 owner
# repository = "xiuos" # 替换为实际的 repository
# calculate(owner,repository)