import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from sklearn.preprocessing import MinMaxScaler

# Load your dataset (replace 'your_dataset.csv' with your actual data file)
data = pd.read_excel('16911279491_DataSampleSent1.xlsx')
data1=data.drop(['TRAINS1','VOVI1','VOVI2','GDQP','Dropout_year'],axis=1)

scaler = MinMaxScaler()
data = scaler.fit_transform(data1)

# Define the VAE architecture
input_dim = data.shape[1]
print(input_dim)
latent_dim = 10

# Encoder
encoder_inputs = keras.Input(shape=(input_dim,))
x = layers.Dense(128, activation='relu')(encoder_inputs)
z_mean = layers.Dense(latent_dim)(x)
z_log_var = layers.Dense(latent_dim)(x)

# Reparameterization
def sampling(args):
    z_mean, z_log_var = args
    epsilon = tf.keras.backend.random_normal(shape=(tf.shape(z_mean)[0], latent_dim), mean=0.0, stddev=1.0)
    return z_mean + tf.exp(0.5 * z_log_var) * epsilon

z = layers.Lambda(sampling)([z_mean, z_log_var])

# Decoder
decoder_inputs = keras.Input(shape=(latent_dim,))
x = layers.Dense(128, activation='relu')(decoder_inputs)
outputs = layers.Dense(input_dim, activation='sigmoid')(x)

# Define the models
encoder = keras.Model(encoder_inputs, [z_mean, z_log_var, z], name='encoder')
decoder = keras.Model(decoder_inputs, outputs, name='decoder')

# VAE model
outputs = decoder(encoder(encoder_inputs)[2])
vae = keras.Model(encoder_inputs, outputs, name='vae')

# VAE loss function
reconstruction_loss = tf.keras.losses.mean_squared_error(encoder_inputs, outputs)
kl_loss = -0.5 * tf.reduce_mean(1 + z_log_var - tf.square(z_mean) - tf.exp(z_log_var))
vae_loss = reconstruction_loss + kl_loss

# Compile the VAE model
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')

# Train the VAE model
print(data.shape)
vae.fit(data, epochs=1000, batch_size=32)

# Generate synthetic data
num_samples = 100000  # Adjust as needed
synthetic_data = decoder.predict(np.random.normal(size=(num_samples, latent_dim)))

# Inverse transform to get data in the original scale
synthetic_data = scaler.inverse_transform(synthetic_data)
# Apply a threshold to the 'Dropout' column
threshold = 0.5
synthetic_data[:, -1] = (synthetic_data[:, -1] >= threshold).astype(int)
synthetic_data=synthetic_data

# Create a DataFrame for the synthetic data
synthetic_df = pd.DataFrame(data=synthetic_data, columns=data1.columns)

# Save the synthetic data to a CSV file
synthetic_df.to_csv('synthetic_data.csv', index=True)
# Save the VAE model if needed
vae.save('vae_model.h5')

import pandas as pd
import cassandra
import re
import os
import glob
import numpy as np
import json
import csv

dataset =pd.read_csv('synthetic_data.csv')

print(dataset)

print(dataset.shape)

print(dataset.columns)

dataset.isnull().sum()

dataset.duplicated().sum()

from cassandra.cluster import Cluster
cluster = Cluster()

# Starting a session to establish connection and begin executing queries
session = cluster.connect()

try:
    session.execute("""
    CREATE KEYSPACE IF NOT EXISTS mykeyspace_student 
    WITH REPLICATION = 
    { 'class' : 'SimpleStrategy', 'replication_factor' : 3 }"""
    )
    session.set_keyspace('mykeyspace_student')
except Exception as e:
    print(e)

create_table_query = """
    CREATE TABLE IF NOT EXISTS mykeyspace_student.std_dropout (
        id int,
        ENGL1 float,
        ENGL2 float,
        ENGL3 float,
        ENGL4 float,
        ENGL5 float,
        ENGL6 float,
        SSL101c float,
        SSG104 float,
        SSC102 float,
        CEA201 float,
        CSD201 float,
        CSI104 float,
        DBI202 float,
        IOT102 float,
        OSG202 float,
        PRF192 float,
        LAB211 float,
        WED201c float,
        PRO192 float,
        PRJ301 float,
        SWE201C float,
        ITE303c float,
        PRN211 float,
        SWR302 float,
        SWT301 float,
        SWP391 float,
        Dropout int,
        PRIMARY KEY (id)
    );
"""
try:
    session.execute(create_table_query)
except Exception as e:
    print(e)     

# Note : before run below cell need to insert the dataset into cassandra using copy cqlsh query
# 
# Dataset -->COPY std_dropout (id, ENGL1, ENGL2, ENGL3, ENGL4, ENGL5, ENGL6, SSL101c,SSG104, SSC102,CEA201, CSD201,CSI104, DBI202,IOT102,OSG202, PRF192, LAB211, WED201c, PRO192, PRJ301,SWE201C,ITE303c,PRN211,SWR302,SWT301,SWP391,Dropout) FROM 'F:\code\49952_Dropout\synthetic_data.csv' WITH DELIMITER =',' AND HEADER=TRUE ;
# 

import findspark
findspark.init()
findspark.find()
import pyspark
findspark.find()

import os

os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages com.datastax.spark:spark-cassandra-connector_2.12:3.1.1 --conf spark.cassandra.connection.host=127.0.0.1 pyspark-shell'

from pyspark import SparkContext

sc = SparkContext("local[*]", "My App")

from pyspark.sql import SQLContext
sqlContext = SQLContext(sc)

def load_and_get_table_df(keys_space_name, table_name):
    table_df = sqlContext.read.format("org.apache.spark.sql.cassandra").options(table=table_name, keyspace=keys_space_name).load()
    print('table_df',table_df)
    return table_df

df = load_and_get_table_df("mykeyspace_student", 'std_dropout')

df.count()

df.head(10)

from pyspark.sql import functions as f
from pyspark.sql.types import IntegerType


# # Outlier detection

def find_outliers(df):

    for column in df.columns:

        less_Q1 = 'less_Q1_{}'.format(column)
        more_Q3 = 'more_Q3_{}'.format(column)
        Q1 = 'Q1_{}'.format(column)
        Q3 = 'Q3_{}'.format(column)

        # Q1 : First Quartile ., Q3 : Third Quartile
        Q1 = df.approxQuantile(column,[0.25],relativeError=0)
        Q3 = df.approxQuantile(column,[0.75],relativeError=0)
        
        # IQR : Inter Quantile Range
       
        
        IQR = Q3[0] - Q1[0]
        
        #selecting the data, with -1.5*IQR to + 1.5*IQR., where param = 1.5 default value
        less_Q1 =  Q1[0] - 1.5*IQR
        more_Q3 =  Q3[0] + 1.5*IQR
        
        isOutlierCol = 'is_outlier_{}'.format(column)
        
        df = df.withColumn(isOutlierCol,f.when((df[column] > more_Q3) | (df[column] < less_Q1), 1).otherwise(0))
    

    # Selecting the specific columns which we have added above, to check if there are any outliers
    selected_columns = [column for column in df.columns if column.startswith("is_outlier")]

    # Adding all the outlier columns into a new colum "total_outliers", to see the total number of outliers
    df = df.withColumn('total_outliers',sum(df[column] for column in selected_columns))

    
    df = df.drop(*[column for column in df.columns if column.startswith("is_outlier")])

    return df

new_df = find_outliers(df)


new_df_with_no_outliers = new_df.filter(new_df['total_Outliers']<=1)
new_df_with_no_outliers = new_df_with_no_outliers.select(*df.columns)

new_df_with_no_outliers.show()

new_df_with_no_outliers.count()


# def remove_outliers_iqr(df, column_name):
#     q1 = df[column_name].quantile(0.25)
#     q3 = df[column_name].quantile(0.75)
#     iqr = q3 - q1

#     lower_bound = q1 - 1.5 * iqr
#     upper_bound = q3 + 1.5 * iqr

#     outliers = (df[column_name] < lower_bound) | (df[column_name] > upper_bound)
#     df_no_outliers = df[~outliers]

#     return df_no_outliers

# df=dataset

# for column in df.columns[:-1]:
#     new_df_with_no_outliers=remove_outliers_iqr(df,column)

new_df_with_no_outliers=new_df_with_no_outliers.drop('id',axis=1)


# # Correlated Features

#plot the correlation matrix
import matplotlib.pyplot as plt
import seaborn as sns

corr_matrix =new_df_with_no_outliers.corr()
top_corr_features=corr_matrix.index
plt.figure(figsize=(15,12))
corr_plot=sns.heatmap(new_df_with_no_outliers[top_corr_features].corr(),annot=True,cmap="Accent")

def correlation(dataset, threshold):
    col_corr = set()  # Set of all the names of correlated columns
    corr_matrix = dataset.corr()
    for i in range(len(corr_matrix.columns)):
        for j in range(i):
            if (corr_matrix.iloc[i, j]) > threshold: # we are interested in absolute coeff value
                colname = corr_matrix.columns[i]  # getting the name of column
                col_corr.add(colname)
    return col_corr

#check the above 0.9 correlated features
corr_features = correlation(new_df_with_no_outliers, 0.9)
len(set(corr_features))

new_df_with_no_outliers

Features =new_df_with_no_outliers.drop('Dropout',axis=1)

Labels=new_df_with_no_outliers['Dropout']

Labels.value_counts()


# # 	Chi-square  for Feature selection

# from sklearn.feature_selection import SelectKBest
# from sklearn.feature_selection import chi2
# chi2_features = SelectKBest(chi2, k = 10)
# X_kbest_features = chi2_features.fit_transform(Features, Labels)

# selected_feature_indices = chi2_features.get_support()
# selected_feature_names = [Features.columns[i] for i, selected in enumerate(selected_feature_indices) if selected]

# print("Selected feature column names:")
# print(selected_feature_names)

# print('Original feature number:', Features.shape[1])
# print('Reduced feature number:', X_kbest_features.shape[1])


# # Data Scaling 

from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()
X_kbest_features=scaler.fit_transform(Features)

labeled_X_kbest_features =X_kbest_features[0:25000]

labeled_X_kbest_features.shape

unlabeled_X_kbest_features =X_kbest_features[25000:30000]

unlabeled_X_kbest_features.shape

print(-np.ones(unlabeled_X_kbest_features.shape[0]))

labeled_X_kbest_features.shape

unlabeled_X_kbest_features.shape

Labels.shape

unlabeled_X_kbest_features.shape


# # Hybrid Model for Student Dropout prediction (DeepS3VM)
# 
# DeepS3VM -->Hybrid s3vm with RNN 

# Step 1: Train a base S3VM model
from sklearn.svm import SVC
from sklearn.semi_supervised import LabelPropagation,SelfTrainingClassifier
svm = SVC(kernel='rbf',probability=True)
base_s3vm_model = SelfTrainingClassifier(svm)
#base_s3vm_model = LabelPropagation(kernel='rbf')
base_s3vm_model.fit(np.vstack((labeled_X_kbest_features, unlabeled_X_kbest_features)), np.hstack((Labels[0:25000], -np.ones(unlabeled_X_kbest_features.shape[0]))))

import pickle

with open('svm_model_weights.pkl', 'wb') as file:
    pickle.dump(base_s3vm_model, file)

with open('svm_model_weights.pkl', 'rb') as file:
    loaded_svm_model = pickle.load(file)

base_s3vm_model=loaded_svm_model

from keras.models import Sequential
from keras.layers import LSTM, Dense,SimpleRNN
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

X_train, X_test, y_train, y_test = train_test_split(labeled_X_kbest_features, Labels[0:25000], test_size=0.25, random_state=42)

rnn_model = Sequential()
rnn_model.add(SimpleRNN(units=64, input_shape=(labeled_X_kbest_features.shape[1], 1)))
#rnn_model.add(Dense(units=128,activation='relu'))
#rnn_model.add(Dense(units=64,activation='relu'))
rnn_model.add(Dense(units=1, activation='sigmoid'))
rnn_model.compile(optimizer='adam',loss='binary_crossentropy',metrics='accuracy')
rnn_model.fit(X_train,y_train,epochs=10,validation_split=0.2)

def hybrid_model_predict(X):
    s3vm_predictions = base_s3vm_model.predict(X)
    rnn_predictions = rnn_model.predict(X.reshape(X.shape[0], X.shape[1], 1))

    
    return (s3vm_predictions + rnn_predictions.flatten()) / 2.0

hybrid_predictions = hybrid_model_predict(X_test)
hybrid_accuracy = accuracy_score(y_test, hybrid_predictions.round())
print('Hybrid Model Accuracy:', hybrid_accuracy)

from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score ,roc_auc_score, roc_curve
hybrid_accuracy = accuracy_score(y_test, hybrid_predictions.round())
print('Hybrid Model Accuracy:', hybrid_accuracy)
hybrid_precision = precision_score(y_test, hybrid_predictions.round())
print('Hybrid Model Precision:', hybrid_precision)
hybrid_recall = recall_score(y_test, hybrid_predictions.round())
print('Hybrid Model Recall:', hybrid_recall)
hybrid_f1score = f1_score(y_test, hybrid_predictions.round())
print('Hybrid Model F1score:', hybrid_f1score)
from sklearn.metrics import classification_report
classification_report = classification_report(y_test, hybrid_predictions.round())
print(classification_report)
import matplotlib.pyplot as plt
import numpy
from sklearn import metrics
confusion_matrix = metrics.confusion_matrix(y_test,  hybrid_predictions.round())

cm_display = metrics.ConfusionMatrixDisplay(confusion_matrix = confusion_matrix, display_labels = [0, 1])

cm_display.plot()
plt.title('Confusion Matrix(DeepS3VM)')
plt.show()
import matplotlib.pyplot as plt

def plot_roc_curve(true_y, y_prob):
    """
    plots the roc curve based of the probabilities
    """

    fpr, tpr, thresholds = roc_curve(true_y, y_prob)
    plt.plot(fpr, tpr)
    plt.title('ROC curve(DeepS3VM)')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
plot_roc_curve(y_test,  hybrid_predictions.round())
hybrid_AUC=roc_auc_score(y_test,  hybrid_predictions.round())
print(f'Hybrid Model AUC score: {roc_auc_score(y_test,  hybrid_predictions.round())}')

from sklearn import tree

model =tree.DecisionTreeClassifier()
model=model.fit(X_train,y_train)
yhat = model.predict(X_test)
DT_accuracy = accuracy_score(y_test, yhat)
print('DT Accuracy:', DT_accuracy)
DT_precision = precision_score(y_test, yhat)
print('DT Precision:', DT_precision)
DT_recall = recall_score(y_test, yhat)
print('DT Recall:', DT_recall)
DT_f1score = f1_score(y_test, yhat)
print('DT F1score:', DT_f1score)
from sklearn.metrics import classification_report
classification_report = classification_report(y_test, yhat)
print(classification_report)
import matplotlib.pyplot as plt
import numpy
from sklearn import metrics
confusion_matrix = metrics.confusion_matrix(y_test,  yhat)

cm_display = metrics.ConfusionMatrixDisplay(confusion_matrix = confusion_matrix, display_labels = [0, 1])

cm_display.plot()
plt.title('Confusion Matrix(Decision Tree)')
plt.show()
import matplotlib.pyplot as plt

def plot_roc_curve(true_y, y_prob):
    """
    plots the roc curve based of the probabilities
    """

    fpr, tpr, thresholds = roc_curve(true_y, y_prob)
    plt.plot(fpr, tpr)
    plt.title('ROC curve(Decision Tree)')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
plot_roc_curve(y_test,  yhat)
DT_auc =roc_auc_score(y_test,  yhat)
print(f'DT Model AUC score: {roc_auc_score(y_test,  yhat)}')

from sklearn.ensemble import RandomForestClassifier

#Create a Gaussian Classifier
clf=RandomForestClassifier(n_estimators=2)

#Train the model using the training sets y_pred=clf.predict(X_test)
clf.fit(X_train,y_train)

yhat=clf.predict(X_test)
RF_accuracy = accuracy_score(y_test, yhat)
print('RF Accuracy:', RF_accuracy)
RF_precision = precision_score(y_test, yhat)
print('RF Precision:', RF_precision)
RF_recall = recall_score(y_test, yhat)
print('RF Recall:', RF_recall)
RF_f1score = f1_score(y_test, yhat)
print('RF F1score:', RF_f1score)
from sklearn.metrics import classification_report
classification_report = classification_report(y_test, yhat)
print(classification_report)
import matplotlib.pyplot as plt
import numpy
from sklearn import metrics
confusion_matrix = metrics.confusion_matrix(y_test,  yhat)

cm_display = metrics.ConfusionMatrixDisplay(confusion_matrix = confusion_matrix, display_labels = [0, 1])

cm_display.plot()
plt.title('Confusion Matrix(Random Forest)')
plt.show()
import matplotlib.pyplot as plt

def plot_roc_curve(true_y, y_prob):
    """
    plots the roc curve based of the probabilities
    """

    fpr, tpr, thresholds = roc_curve(true_y, y_prob)
    plt.plot(fpr, tpr)
    plt.title('ROC curve(Random Forest)')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
plot_roc_curve(y_test,  yhat)
RF_auc =roc_auc_score(y_test,  yhat)
print(f'RF Model AUC score: {roc_auc_score(y_test,  yhat)}')

from xgboost import XGBClassifier
from sklearn.model_selection import cross_val_score

# fit model no training data
xgboost = XGBClassifier(learning_rate =0.9,n_estimators=1000,max_depth=5,min_child_weight=1,gamma=0,subsample=0.7,colsample_bytree=0.7,objective= 'binary:logistic',nthread=4,scale_pos_weight=1,seed=1000)
xgboost.fit(X_train, y_train)

yhat=xgboost.predict(X_test)
xgboost_accuracy = accuracy_score(y_test, yhat)
print('xgboost Accuracy:', xgboost_accuracy)
xgboost_precision = precision_score(y_test, yhat)
print('xgboost Precision:', xgboost_precision)
xgboost_recall = recall_score(y_test, yhat)
print('xgboost Recall:', xgboost_recall)
xgboost_f1score = f1_score(y_test, yhat)
print('xgboost F1score:', xgboost_f1score)
from sklearn.metrics import classification_report
classification_report = classification_report(y_test, yhat)
print(classification_report)
import matplotlib.pyplot as plt
import numpy
from sklearn import metrics
confusion_matrix = metrics.confusion_matrix(y_test,  yhat)

cm_display = metrics.ConfusionMatrixDisplay(confusion_matrix = confusion_matrix, display_labels = [0, 1])

cm_display.plot()
plt.title('Confusion Matrix(XGBoost)')
plt.show()
import matplotlib.pyplot as plt

def plot_roc_curve(true_y, y_prob):
    """
    plots the roc curve based of the probabilities
    """

    fpr, tpr, thresholds = roc_curve(true_y, y_prob)
    plt.plot(fpr, tpr)
    plt.title('ROC curve(XGBoost)')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
plot_roc_curve(y_test,  yhat)
xgboos_auc=roc_auc_score(y_test,  yhat)
print(f'xgboost Model AUC score: {roc_auc_score(y_test,  yhat)}')

print(X_train.shape)

ann_model = Sequential()
ann_model.add(Dense(units=1024, input_dim=X_train.shape[1], kernel_initializer='uniform', activation='relu'))
ann_model.add(Dense(units=512, kernel_initializer='uniform', activation='relu'))
ann_model.add(Dense(units=1, kernel_initializer='uniform', activation='sigmoid'))
ann_model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
ann_model.fit(X_train,y_train,epochs=5,validation_split=0.2)
ann_model.save('ann_model.h5')

from keras.models import load_model
ann_model=load_model('ann_model.h5')

yhat=ann_model.predict(X_test)
yhat = np.where(yhat >=0.5, 1, 0)

#hat =np.argmax(yhat,axis=1)
ann_model_accuracy = accuracy_score(y_test, yhat)
print('ANN Accuracy:', ann_model_accuracy)
ann_model_precision = precision_score(y_test, yhat)
print('ANN Precision:', ann_model_precision)
ann_model_recall = recall_score(y_test, yhat)
print('ANN Recall:', ann_model_recall)
ann_model_f1score = f1_score(y_test, yhat)
print('ANN F1score:', ann_model_f1score)
from sklearn.metrics import classification_report
classification_report = classification_report(y_test, yhat)
print(classification_report)
import matplotlib.pyplot as plt
import numpy
from sklearn import metrics
confusion_matrix = metrics.confusion_matrix(y_test,  yhat)

cm_display = metrics.ConfusionMatrixDisplay(confusion_matrix = confusion_matrix, display_labels = [0, 1])

cm_display.plot()
plt.title('Confusion Matrix(ANN)')
plt.show()
import matplotlib.pyplot as plt

def plot_roc_curve(true_y, y_prob):
    """
    plots the roc curve based of the probabilities
    """

    fpr, tpr, thresholds = roc_curve(true_y, y_prob)
    plt.plot(fpr, tpr)
    plt.title('ROC curve(ANN)')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
plot_roc_curve(y_test,  yhat)
ann_model_auc=roc_auc_score(y_test,  yhat)
print(f'ANN Model AUC score: {roc_auc_score(y_test,  yhat)}')

import tensorflow as tf
from tensorflow.keras.layers import Flatten, Dense, Conv1D, MaxPooling1D, Dropout

cnn_model = Sequential()
cnn_model.add(Conv1D(32, 1, activation="relu", input_shape=(X_train.shape[1],1)))
cnn_model.add(Dense(16, activation="relu"))
cnn_model.add(MaxPooling1D())
cnn_model.add(Flatten())
cnn_model.add(Dropout(0.5))
cnn_model.add(Dense(1, activation = 'sigmoid'))
cnn_model.compile(loss = 'binary_crossentropy', optimizer = "adam",metrics = ['accuracy'])
cnn_model_history = cnn_model.fit(X_train, y_train, epochs=5,validation_split=0.2)

yhat=cnn_model.predict(X_test)
yhat = np.where(yhat > 0.5, 1, 0)

#hat =np.argmax(yhat,axis=1)
cnn_model_accuracy = accuracy_score(y_test, yhat)
print('CNN Accuracy:', cnn_model_accuracy)
cnn_model_precision = precision_score(y_test, yhat)
print('CNN Precision:', cnn_model_precision)
cnn_model_recall = recall_score(y_test, yhat)
print('CNN Recall:', cnn_model_recall)
cnn_model_f1score = f1_score(y_test, yhat)
print('CNN F1score:', cnn_model_f1score)
from sklearn.metrics import classification_report
classification_report = classification_report(y_test, yhat)
print(classification_report)
import matplotlib.pyplot as plt
import numpy
from sklearn import metrics
confusion_matrix = metrics.confusion_matrix(y_test,  yhat)

cm_display = metrics.ConfusionMatrixDisplay(confusion_matrix = confusion_matrix, display_labels = [0, 1])

cm_display.plot()
plt.title('Confusion Matrix(CNN)')
plt.show()
import matplotlib.pyplot as plt

def plot_roc_curve(true_y, y_prob):
    """
    plots the roc curve based of the probabilities
    """

    fpr, tpr, thresholds = roc_curve(true_y, y_prob)
    plt.plot(fpr, tpr)
    plt.title('ROC curve(CNN)')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
plot_roc_curve(y_test,  yhat)
cnn_model_auc=roc_auc_score(y_test,  yhat)
print(f'CNN Model AUC score: {roc_auc_score(y_test,  yhat)}')

import numpy as np
import matplotlib.pyplot as plt

# Sample data for models and metrics
models = ['Random Forest','Decision Tree', 'XgBoost','ANN','CNN', 'DeepS3VM']
accuracy = [RF_accuracy,DT_accuracy,xgboost_accuracy,ann_model_accuracy,cnn_model_accuracy,hybrid_accuracy]
precision = [RF_precision,DT_precision,xgboost_precision,ann_model_precision,cnn_model_precision,hybrid_precision]
recall = [RF_recall,DT_recall,xgboost_recall,ann_model_recall,cnn_model_recall,hybrid_recall]
f1 = [RF_f1score,DT_f1score,xgboost_f1score,ann_model_f1score,cnn_model_f1score,hybrid_f1score]
auc_scores = [RF_auc,DT_auc,xgboos_auc,ann_model_auc,cnn_model_auc,hybrid_AUC]

# Set width of bar
barWidth = 0.1

# Set position of bars on X axis
r1 = np.arange(len(accuracy))
r2 = [x + barWidth for x in r1]
r3 = [x + barWidth for x in r2]
r4 = [x + barWidth for x in r3]
r5 = [x + barWidth for x in r4]

# Create a figure and axis with specified size and style
plt.figure(figsize=(18, 7))
plt.style.use('Solarize_Light2')

# Plot the bars with custom colors
plt.bar(r1, accuracy, color='#1CBF7A', width=barWidth, edgecolor='white', label='Accuracy')
plt.bar(r2, precision, color='#31C2D6', width=barWidth, edgecolor='white', label='Precision')
plt.bar(r3, recall, color='#C0D510', width=barWidth, edgecolor='white', label='Recall')
plt.bar(r4, f1, color='#CF9B8F', width=barWidth, edgecolor='white', label='F1 Score')
plt.bar(r5, auc_scores, color='#797D7F', width=barWidth, edgecolor='white', label='AUC Score')

# Add labels and title with customized font size and weight
plt.xlabel('Classification Models', fontweight='bold', fontsize=14)
plt.ylabel('Metrics', fontweight='bold', fontsize=14)
plt.xticks([r + 2.5 * barWidth for r in range(len(accuracy))], models, fontsize=12)
plt.title('Comparison of Model Performance Metrics', fontsize=16)
for i, v in enumerate(accuracy):
    plt.text(i, v, f'{v:.2f}', ha='center', va='bottom',fontsize=9)
    plt.text(i + barWidth, precision[i], f'{precision[i]:.2f}', ha='center', va='bottom',fontsize=9)
    plt.text(i + 2 * barWidth, recall[i], f'{recall[i]:.2f}', ha='center', va='bottom',fontsize=9)
    plt.text(i + 3 * barWidth, f1[i], f'{f1[i]:.2f}', ha='center', va='bottom',fontsize=9)
    plt.text(i + 4 * barWidth, auc_scores[i], f'{auc_scores[i]:.2f}', ha='center', va='bottom',fontsize=9)

# Add legend
#plt.legend(fontsize=12)
plt.legend(fontsize=12,bbox_to_anchor=(1.05, 1.0), loc='upper left')
# Show plot with a tight layout
plt.tight_layout()

# Save the plot as an image (optional)
plt.savefig('model_metrics_comparison.png', dpi=300)

# Display the plot
plt.show()


# # Personalized Recommendation System

ENGL1=input('Enter the Input for ENGL1')
ENGL2=input('Enter the Input for ENGL2')
ENGL3=input('Enter the Input for ENGL3')
ENGL4=input('Enter the Input for ENGL4')
ENGL5=input('Enter the Input for ENGL5')
ENGL6=input('Enter the Input for ENGL6')
SSL101cÂ=input('Enter the Input for SSL101cÂ')
SSG104=input('Enter the Input for SSG104')
SSC102=input('Enter the Input for SSC102')
CEA201=input('Enter the Input for CEA201')
CSD201=input('Enter the Input for CSD201')
CSI104=input('Enter the Input for CSI104')
DBI202=input('Enter the Input for DBI202')
IOT102=input('Enter the Input for IOT102')
OSG202=input('Enter the Input for OSG202')
PRF192=input('Enter the Input for PRF192')
LAB211=input('Enter the Input for LAB211')
WED201c=input('Enter the Input for WED201c')
PRO192=input('Enter the Input for PRO192')
PRJ301=input('Enter the Input for PRJ301')
SWE201C=input('Enter the Input for SWE201C')
ITE303c=input('Enter the Input for ITE303c')
PRN211=input('Enter the Input for PRN211')
SWR302=input('Enter the Input for SWR302')
SWT301=input('Enter the Input for SWT301')
SWP391=input('Enter the Input for SWP391')
																									
new_student_data = pd.DataFrame({
    'ENGL1':[float(ENGL1)],  
    'ENGL2':[float(ENGL2)],
    'ENGL3':[float(ENGL3)],
    'ENGL4':[float(ENGL4)],
    'ENGL5':[float(ENGL5)],
    'ENGL6':[float(ENGL6)],
    'Academic Skills for University Success':[float(SSL101cÂ)],
    'Communication and In-Group Working Skills':[float(SSG104)],
    'Business Communication':[float(SSC102)],
    'Computer Organization and Architecture':[float(CEA201)],
    'Data Structures and Algorithms':[float(CSD201)],
    'Introduction to computing':[float(CSI104)],
    'Database Systems':[float(DBI202)],
    'Internet of Things':[float(IOT102)],
    'Operating Systems':[float(OSG202)],
    'Programming Fundamentals':[float(PRF192)],
    'OOP with Java Lab':[float(LAB211)],
    'Web Design':[float(WED201c)],
    'Object-Oriented Programming':[float(PRO192)],
    'Java Web application development':[float(PRJ301)],
    'Introduction to Software Engineering':[float(SWE201C)],
    'Ethics in IT':[float(ITE303c)],
    'Basic Cross-Platform Application Programming With .NET':[float(PRN211)],
    'Software Requirements':[float(SWR302)],
    'Software Testing':[float(SWT301)],
    'Software development project':[float(SWP391)],
    
})

new_student_data

from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()
new_student_data_scaler=scaler.fit_transform(new_student_data)

hybrid_predictions_new_data = hybrid_model_predict(new_student_data_scaler)

hybrid_predictions_new_data

# Make a prediction for the new student
#dropout_prediction = dropout_model.predict(new_student_data)

if hybrid_predictions_new_data >= 0.5:
    print("This student is at risk of dropping out.")
    print('\n')
    recommended_subjects = new_student_data.mean().sort_values(ascending=False).index
    print("Top10 Recommended subjects for this student:")
    print(recommended_subjects[:10].values)
else:
    print("This student is not at risk of dropping out.")