diff --git a/data/data.csv b/src/data/data.csv similarity index 72% rename from data/data.csv rename to src/data/data.csv index 4d6f9a1..a65bec2 100644 --- a/data/data.csv +++ b/src/data/data.csv @@ -1,4 +1,2 @@ id,project_name,repo_name,language,version_tag,version_github_tag,repo_url,version_start_date,version_end_date,i1_robustness,i2_scalability,i3_usability,i4_effectiveness,i5_corrections,i6_improvements,i7_security,i8_testing_process,i9_coverage,i10_license_type,i11_dual_licensing,i12_commercial_resources,i13_commercial_training,i14_industry_adoption,i15_ngo_support,i16_corporate_support,i17_donations,i18_installability,i19_configurability,i20_self_contained,i21_resource_utilization,i22_complexity,i23_modularity,i24_instability,i25_cohesion,i26_governance_model,i27_project_road_map,i28_code_of_conduct,i29_coding_standards,i30_documentation_standards,i31_devs_attracted,i32_devs_active,i33_nof_open_issues,i34_open_vs_closed_issues,i35_documendation,i36_localization_process,i37_issue_tracking,i38_user_guide,g1_architecture,g2_maintenability,g3_security_testing,g4_license,g5_market,g6_support,g7_initialization,g8_dependencies,g9_reuse,g10_dev_process_governance,g11_developer_base,g12_user_base,d1_source_code,d2_business_legal,d3_integration_reuse,d4_social,analysis_complete,auto_expert_value -1,WP Gutenberg,WordPress/gutenberg,PHP,1,v0.1.0,https://github.com/WordPress/gutenberg,2017-06-16,2017-06-23,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1.0,3 -2,PHP Mailer,PHPMailer/PHPMailer,PHP,6.5.4,v6.5.4,https://github.com/PHPMailer/PHPMailer,2021-11-25,2022-02-17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1.0,3 -3,PHP Word,PHPOffice/PHPWord,PHP,0.18.2,0.18.2,https://github.com/PHPOffice/PHPWord,2021-06-04,2022-02-17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3 +1,PHP Word,PHPOffice/PHPWord,PHP,0.18.2,0.18.2,https://github.com/PHPOffice/PHPWord,2021-06-04,2022-02-17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,3 diff --git a/ossrf.py b/src/ossrf.py similarity index 98% rename from ossrf.py rename to src/ossrf.py index bdcb8a5..f1b6eef 100644 --- a/ossrf.py +++ b/src/ossrf.py @@ -581,10 +581,10 @@ def main(): d4_bar = d4 ind = np.arange(N) width = 0.15 - plt.bar(ind, d1_bar, width, color='darkgreen', label='Source Code') - plt.bar(ind + width, d2_bar, width, color='royalblue', label='Business & Legal') - plt.bar(ind + 2*width, d3_bar, width, color='gold', label='Integration & Reuse') - plt.bar(ind + 3*width, d4_bar, width, color='slateblue', label='Social') + plt.bar(ind, d1_bar, width, color='blue', label='Source Code') + plt.bar(ind + width, d2_bar, width, color='orange', label='Business & Legal') + plt.bar(ind + 2*width, d3_bar, width, color='green', label='Integration & Reuse') + plt.bar(ind + 3*width, d4_bar, width, color='red', label='Social') plt.ylabel('Scores') plt.title('Dimensions') #plt.xticks(ind + width / 2, ('D1', 'D2', 'D3', 'D4')) @@ -593,7 +593,8 @@ def main(): out_bar = "./data/" + project_name + "_bar.png" plt.savefig(out_bar) # Show plot - #plt.show() + #plt.show() + """ #Pie chart ## Clear the plot to start with a blank canvas plt.clf() @@ -611,7 +612,8 @@ def main(): out_pie = "./data/" + project_name + "_pie.png" plt.savefig(out_pie) #Show plot - #plt.show() + #plt.show() + """ logging.info("Visualizations done!") # Update row when analysis is complete (analysis_complete = YES) df.at[index,'analysis_complete'] = 1 diff --git a/src/rfoss/data/composer_140.csv b/src/rfoss/data/composer_140.csv new file mode 100644 index 0000000..6167a7e --- /dev/null +++ b/src/rfoss/data/composer_140.csv @@ -0,0 +1,39 @@ +Indicator Name,Indicator ID,Score +Robustness,I01,0.6 +Scalability,I02,0.6 +Usability,I03,0.6 +Effectiveness,I04,0.5 +Corrections,I05,0.6 +Improvements,I06,0.6 +Security,I07,0.6 +Testing process,I08,1 +Coverage,I09,0.89 +License type,I10,1 +Dual licensing,I11,0 +Commercial resources,I12,1 +Commercial training,I13,1 +Industry adoption,I14,1 +Non profit / Foundation support,I15,1 +For profit company support,I16,1 +Donations,I17,0 +Installability,I18,0.6 +Configurability,I19,0.6 +Self-contained,I20,0.6 +Resource Utilization,I21,0.6 +Complexity,I22,0.8 +Modularity,I23,0.6 +Instability,I24,0.54 +Cohesion,I25,0.67 +Governance model,I26,0 +Project Road-map,I27,1 +Code of conduct,I28,1 +Coding standards,I29,1 +Documentation standards,I30,1 +Developers Attracted,I31,0.11 +Active Developers,I32,0.33 +Number of open issues,I33,0.95 +Open / Closed issues,I34,0.96 +Source Code Documentation,I35,0.8 +Localization process,I36,1 +Issue tracking activity (reporting bugs),I37,0.05 +User guide (completeness),I38,1 diff --git a/src/rfoss/output/composer_140.txt b/src/rfoss/output/composer_140.txt new file mode 100644 index 0000000..61ee5b8 --- /dev/null +++ b/src/rfoss/output/composer_140.txt @@ -0,0 +1,25 @@ +RFOSS Scores: + +D1. Source Code: 67% + +G01. Architecture: 57% +G02. Maintainability: 60% +G03. Security & Testing: 83% + +D2. Business & Legal: 81% + +G04. License: 100% +G05. Market: 75% +G06. Support: 67% + +D3. Integration & Reuse: 62% + +G07. Initialization: 60% +G08. Dependencies: 60% +G09. Reuse: 65% + +D4. Social (Community): 70% + +G10. Development process & Governance: 80% +G11. Developer Base: 63% +G12. User Base: 68% \ No newline at end of file diff --git a/src/rfoss/output/composer_140_bar.png b/src/rfoss/output/composer_140_bar.png new file mode 100644 index 0000000..de268ea Binary files /dev/null and b/src/rfoss/output/composer_140_bar.png differ diff --git a/src/rfoss/output/composer_140_radar.png b/src/rfoss/output/composer_140_radar.png new file mode 100644 index 0000000..52c0a07 Binary files /dev/null and b/src/rfoss/output/composer_140_radar.png differ diff --git a/src/rfoss/rfoss.py b/src/rfoss/rfoss.py new file mode 100644 index 0000000..95f05bd --- /dev/null +++ b/src/rfoss/rfoss.py @@ -0,0 +1,264 @@ +#### +### +## +# Resilience Framework for OSS (RFOSS) +# Author: Apostolos Kritikos +# Version: 1.0 +# +# This source code is part of my PhD thesis, entitled "Open +# Source Software Engineering" in cooperation with the Informatics +# Department of the Aristotle University of Thessaloniki. +# +# The PhD is happening under the supervision of Prof. Ioannis Stamelos. +# +# This research is co-financed by Greece and the European Union +# (European Social Fund- ESF) through the Operational Programme +# «Human Resources Development, Education and Lifelong Learning» +# in the context of the project “Strengthening Human Resources +# Research Potential via Doctorate Research” (MIS-5000432), +# implemented by the State Scholarships Foundation (ΙΚY). +# +## +### +#### + +import os +import csv +import pandas as pd +from math import pi +import matplotlib.pyplot as plt +import numpy as np + +# Directory of csv files +directory = "./data/" + +# Initialize indicators array +indicators = {} + +# Iterate over csv files (select only csv files) +for filename in os.listdir(directory): + if filename.endswith(".csv"): + # Directory + filename + finalfilename = directory+filename + # Open single csv file for read + with open(finalfilename, newline='') as csvfile: + reader = csv.reader(csvfile, delimiter=',') + for row in reader: + key = row[1] + if key in indicators: + # implement your duplicate row handling here + pass + if row[2] != 'Score': + indicators[key] = float(row[2]) + # Get project name from filename + temp = csvfile.name + temp1 = temp.split("/") + temp2 = temp1[2].split(".") + project_name = temp2[0] + + # Calculate Goals + g1 = ( indicators[ 'I01' ] + indicators[ 'I02' ] + indicators[ 'I03' ] + indicators[ 'I04' ] ) / 4 + g1_str = str( int( round( g1 * 100 ) ) ) + "%" + + g2 = ( indicators[ 'I05' ] + indicators[ 'I06' ] ) / 2 + g2_str = str( int( round( g2 * 100 ) ) ) + "%" + + g3 = ( indicators[ 'I07' ] + indicators[ 'I08' ] + indicators[ 'I09' ]) / 3 + g3_str = str( int( round( g3 * 100 ) ) ) + "%" + + g4 = indicators[ 'I10' ] + g4_str = str( int( round( g4 * 100 ) ) ) + "%" + + g5 = ( indicators[ 'I11' ] + indicators[ 'I12' ] + indicators[ 'I13' ] + indicators[ 'I14' ] ) / 4 + g5_str = str( int( round( g5 * 100 ) ) ) + "%" + + g6 = ( indicators[ 'I15' ] + indicators[ 'I16' ] + indicators[ 'I17' ] ) / 3 + g6_str = str( int( round( g6 * 100 ) ) ) + "%" + + g7 = ( indicators[ 'I18' ] + indicators[ 'I19' ] ) / 2 + g7_str = str( int( round( g7 * 100 ) ) ) + "%" + + g8 = ( indicators[ 'I20' ] + indicators[ 'I21' ] ) / 2 + g8_str = str( int( round( g8 * 100 ) ) ) + "%" + + g9 = ( indicators[ 'I22' ] + indicators[ 'I23' ] + indicators[ 'I24' ] + indicators[ 'I25' ] ) / 4 + g9_str = str( int( round( g9 * 100 ) ) ) + "%" + + g10 = ( indicators[ 'I26' ] + indicators[ 'I27' ] + indicators[ 'I28' ] + indicators[ 'I29' ] + indicators[ 'I30' ] ) / 5 + g10_str = str( int( round( g10 * 100 ) ) ) + "%" + + g11 = ( indicators[ 'I31' ] + indicators[ 'I32' ] + indicators[ 'I33' ] + indicators[ 'I34' ] + indicators[ 'I35' ] ) / 5 + g11_str = str( int( round( g11 * 100 ) ) ) + "%" + + g12 = ( indicators[ 'I36' ] + indicators[ 'I37' ] + indicators[ 'I38' ] ) / 3 + g12_str = str( int( round( g12 * 100 ) ) ) + "%" + + # Calculate Dimensions + d1 = ( g1 + g2 + g3 ) / 3 + d1_str = str( int( round( d1 * 100 ) ) ) + "%" + + d2 = ( g4 + g5 + g6 ) / 3 + d2_str = str( int( round( d2 * 100 ) ) ) + "%" + + d3 = ( g7 + g8 + g9 ) / 3 + d3_str = str( int( round( d3 * 100 ) ) ) + "%" + + d4 = ( g10 + g11 + g12 ) / 3 + d4_str = str( int( round( d4 * 100 ) ) ) + "%" + + # Results + + # Write results to file + out_filename = "./output/" + project_name + ".txt" + f = open(out_filename, 'w+') + f.write("RFOSS Scores:") + f.write("\n") + f.write("\n") + f.write("D1. Source Code: " + d1_str) + f.write("\n") + f.write("\n") + f.write("G01. Architecture: " + g1_str) + f.write("\nG02. Maintainability: " + g2_str) + f.write("\nG03. Security & Testing: " + g3_str) + f.write("\n") + f.write("\n") + f.write("D2. Business & Legal: " + d2_str) + f.write("\n") + f.write("\n") + f.write("G04. License: " + g4_str) + f.write("\nG05. Market: " + g5_str) + f.write("\nG06. Support: " + g6_str) + f.write("\n") + f.write("\n") + f.write("D3. Integration & Reuse: " + d3_str) + f.write("\n") + f.write("\n") + f.write("G07. Initialization: " + g7_str) + f.write("\nG08. Dependencies: " + g8_str) + f.write("\nG09. Reuse: " + g9_str) + f.write("\n") + f.write("\n") + f.write("D4. Social (Community): " + d4_str) + f.write("\n") + f.write("\n") + f.write("G10. Development process & Governance: " + g10_str) + f.write("\nG11. Developer Base: " + g11_str) + f.write("\nG12. User Base: " + g12_str) + f.close() + + # Visualizations + + # Spider chart based on: https://williamhuster.com/radar-chart-in-python/ + rfoss_goals = { + 'Architecture': g1*100, + 'Maintainability': g2*100, + 'Security & Testing': g3*100, + 'License': g4*100, + 'Market': g5*100, + 'Support': g6*100, + 'Initialization': g7*100, + 'Dependencies': g8*100, + 'Reuse': g9*100, + 'Development process & Governance': g10*100, + 'Developer Base': g11*100, + 'User Base': g12*100 + } + + df = pd.DataFrame([rfoss_goals]) + + skills = list(df) + num_skills = len(skills) + + angles = [i / float(num_skills) * 2 * pi for i in range(num_skills)] + angles += angles[:1] # repeat the first value to close the circle + angles = angles[:-1] + + GRAY = '#999999' + + # Clear the plot to start with a blank canvas. + plt.clf() + + # Create subplots for each data series + series_1 = plt.subplot(1, 1, 1, polar=True) + + # Draw one x-axis per variable and add labels + plt.xticks(angles, skills, color=GRAY, size=8) + + # Draw the y-axis labels. To keep the graph uncluttered, + # include lines and labels at only a few values. + plt.yticks( + [20, 40, 60, 80], + ['20', '40', '60', '80'], + color=GRAY, + size=7 + ) + + # Constrain y axis to range 0-100 + plt.ylim(0,100) + + series_1_values = df.loc[0] \ + .values \ + .flatten() \ + .tolist() + series_1_values += series_1_values[:1] # duplicate first element to close the circle + series_1_values = series_1_values[:-1] + + # Set up colors + ORANGE = '#FD7120' + BLUE = '#00BFFF' + + # Plot the first series + series_1.set_rlabel_position(0) + series_1.plot( + angles, + series_1_values, + color=ORANGE, + linestyle='solid', + linewidth=1, + ) + series_1.fill( + angles, + series_1_values, + color=ORANGE, + alpha=0.6 + ) + + # Save the image + out_radar = "./output/" + project_name + "_radar.png" + plt.savefig(out_radar) + # Show plot + #plt.show() + + + # Bar chart + # Clear the plot to start with a blank canvas. + plt.clf() + + N = 1 + d1_bar = d1 + d2_bar = d2 + d3_bar = d3 + d4_bar = d4 + + ind = np.arange(N) + width = 0.15 + plt.bar(ind, d1_bar, width, label='Source Code') + plt.bar(ind + width, d2_bar, width, label='Business & Legal') + plt.bar(ind + 2*width, d3_bar, width, label='Integration & Reuse') + plt.bar(ind + 3*width, d4_bar, width, label='Social') + + plt.ylabel('Scores') + plt.title('Dimensions') + + #plt.xticks(ind + width / 2, ('D1', 'D2', 'D3', 'D4')) + plt.legend(loc='best') + + # Save the image + out_bar = "./output/" + project_name + "_bar.png" + plt.savefig(out_bar) + # Show plot + #plt.show() + else: + continue + + diff --git a/template/data.csv b/src/template/data.csv similarity index 100% rename from template/data.csv rename to src/template/data.csv