|
| 1 | +from fpdf import FPDF |
| 2 | +from datetime import datetime |
| 3 | +import shutil |
| 4 | +import pandas as pd |
| 5 | +import csv |
| 6 | +import os |
| 7 | + |
| 8 | +baseDir = os.path.join(os.getcwd(), "assets") |
| 9 | +file_to_be_parsed = os.path.join(os.getcwd(), "uploads/grades.csv") |
| 10 | +subNameMapping = os.path.join(os.getcwd(), "uploads/subjects_master.csv") |
| 11 | +studNameMapping = os.path.join(os.getcwd(), "uploads/names-roll.csv") |
| 12 | + |
| 13 | +masterList = [] |
| 14 | +studNameMap = {} |
| 15 | +dfl = {} |
| 16 | +dct = {} |
| 17 | + |
| 18 | +branchMap = { |
| 19 | + "CS": "Computer Science and Engineering", |
| 20 | + "CB": "Chemical Engineering", |
| 21 | + "EE": "Electrical & Electronics Engineering", |
| 22 | + "ME": "Mechanical Engineering", |
| 23 | + "MM": "Metallurgical Engineering", |
| 24 | + "CE": "Civil Engineering", |
| 25 | + "CH": "Chemistry", |
| 26 | +} |
| 27 | + |
| 28 | +gradeMap = { |
| 29 | + "AA": 10, |
| 30 | + "AB": 9, |
| 31 | + "BB": 8, |
| 32 | + "BC": 7, |
| 33 | + "CC": 6, |
| 34 | + "CD": 5, |
| 35 | + "DD": 4, |
| 36 | + "F": 0, |
| 37 | + "I": 0, |
| 38 | +} |
| 39 | + |
| 40 | + |
| 41 | +def prepLists(): |
| 42 | + for ind, line in enumerate(csv.reader(open(studNameMapping))): |
| 43 | + if ind > 0: |
| 44 | + studNameMap[line[0]] = line[1] |
| 45 | + |
| 46 | +def fixWildcardEntry(grade) -> str: |
| 47 | + return grade.replace("*", "") if grade[len(grade) - 1] == "*" else grade |
| 48 | + |
| 49 | + |
| 50 | +def prepOverallResult(rollNum: str): |
| 51 | + spi, cpi = ["SPI"], ["CPI"] |
| 52 | + |
| 53 | + masterList = [] |
| 54 | + for ind, line in enumerate(csv.reader(open(file_to_be_parsed))): |
| 55 | + masterList.append(line) |
| 56 | + |
| 57 | + maxSem = 0 |
| 58 | + |
| 59 | + # Find max sems for a roll no |
| 60 | + for ind, line in enumerate(masterList): |
| 61 | + if line[0] == rollNum: |
| 62 | + maxSem = max(maxSem, int(line[1])) |
| 63 | + maxSem += 1 # As range iterates till maxValue - 1 |
| 64 | + |
| 65 | + semwiseCreds = ["Semester wise Credit Taken"] |
| 66 | + fullCreds = ["Total Credits Taken"] |
| 67 | + clearedCreds = ["Total Credits Cleared"] |
| 68 | + semRow = ["Semester No", 1] |
| 69 | + |
| 70 | + for f in range(1, maxSem): |
| 71 | + ms, cls, spis = 0, 0, 0 |
| 72 | + for ind, line in enumerate(masterList): |
| 73 | + if ind > 0: |
| 74 | + if line[0] == rollNum: # Fix a roll no |
| 75 | + if int(line[1]) == f: # Iterate on a specific sem |
| 76 | + ms += int(line[3]) |
| 77 | + finalGrade = fixWildcardEntry(line[4].strip()) |
| 78 | + if finalGrade == "F" or finalGrade == "I": |
| 79 | + pass |
| 80 | + else: |
| 81 | + cls += int(line[3]) |
| 82 | + spis += int(line[3]) * gradeMap[finalGrade] |
| 83 | + |
| 84 | + # Handle the case for the sem which does not exist |
| 85 | + mSemWiseClsCreds = cls |
| 86 | + mSpi = 0 |
| 87 | + mSemWiseCreds = 0 |
| 88 | + if ms > 0: |
| 89 | + mSpi = (spis / ms).__round__(2) |
| 90 | + mSemWiseCreds = ms |
| 91 | + spi.append(mSpi) |
| 92 | + semwiseCreds.append(mSemWiseCreds) |
| 93 | + clearedCreds.append(mSemWiseClsCreds) |
| 94 | + |
| 95 | + mCpi = spi[1] * semwiseCreds[1] |
| 96 | + dynCreds = semwiseCreds[1] |
| 97 | + fullCreds.append(dynCreds) |
| 98 | + cpi.append(spi[1]) # Because CPI in 1st sem is same as SPI in 1st sem |
| 99 | + |
| 100 | + for sem in range(2, maxSem): |
| 101 | + semRow.append(sem) |
| 102 | + dynCreds += semwiseCreds[sem] |
| 103 | + fullCreds.append(dynCreds) |
| 104 | + mCpi += spi[sem] * semwiseCreds[sem] |
| 105 | + cpi.append((mCpi / dynCreds).__round__(2)) |
| 106 | + |
| 107 | + return maxSem - 1, semwiseCreds, clearedCreds, spi, cpi |
| 108 | + |
| 109 | +def checkForImg(imgName) -> bool: |
| 110 | + conts = os.listdir(os.path.join(os.getcwd(), "uploads")) |
| 111 | + if imgName not in conts: |
| 112 | + return False |
| 113 | + return True |
| 114 | + |
| 115 | +def prepPdfForRolls(rng: []): |
| 116 | + sealAv = checkForImg("seal.jpeg") |
| 117 | + signAv = checkForImg("sign.jpeg") |
| 118 | + for roll in rng: |
| 119 | + dims = {} |
| 120 | + stdims = {} |
| 121 | + txtForSem = {} |
| 122 | + missed = 0 |
| 123 | + if roll in dfl: |
| 124 | + sems, swcreds, clsCreds, spiz, cpiz = prepOverallResult(roll) |
| 125 | + pdf = FPDF(orientation="L", unit="mm", format="A3") |
| 126 | + pdf.add_page() |
| 127 | + pdf.set_font("Times", size=8.5) |
| 128 | + line_height = pdf.font_size * 1.5 |
| 129 | + pdf.rect(x=10, y=10, w=pdf.w - 20, h=pdf.h-20, style="") |
| 130 | + pdf.rect(x=85, y=43, w=(pdf.w / 2) + 20, h=15, style="") |
| 131 | + fmtr = 0 |
| 132 | + pdf.image(os.path.join(os.getcwd(), "assets/tsBanner.png"), x=10, y=10, w=pdf.w - 20) |
| 133 | + prg = "" |
| 134 | + temp = roll |
| 135 | + if str(temp)[2] == '1': |
| 136 | + prg = "Master of Technology" |
| 137 | + if str(temp)[2] == '2': |
| 138 | + prg = "PhD" |
| 139 | + if str(temp)[2] == '0': |
| 140 | + prg = "Bachelor of Technology" |
| 141 | + pdf.set_font(size=12, style="B") |
| 142 | + pdf.text(x=87, y=48, txt=f"Roll No: {roll} Name: {studNameMap[roll]} Year of Admission: 20{roll[0] + roll[1]}") |
| 143 | + pdf.text(x=87, y=55, txt=f"Programme: {prg} Course: {branchMap[str(temp[4] + temp[5])]}") |
| 144 | + |
| 145 | + pdf.set_font(size=10, style="") |
| 146 | + abscissa = 7 |
| 147 | + ordinate = 64 |
| 148 | + recy = 0 |
| 149 | + recx = 0 |
| 150 | + tx = 7 |
| 151 | + pdf.set_y(ordinate+5) |
| 152 | + |
| 153 | + for sem in range(sems): |
| 154 | + indx = 0 |
| 155 | + if (sem) % 4 == 0 and sem > 0: |
| 156 | + pdf.set_x(recx) |
| 157 | + if sem + 1 in dfl[roll].keys(): |
| 158 | + for info in dfl[roll][sem + 1]: |
| 159 | + if abscissa != 0: |
| 160 | + pdf.set_x(abscissa + 8) |
| 161 | + rind = 0 |
| 162 | + wdh = 0 |
| 163 | + ls = len(info) + 1 |
| 164 | + for ir in range(ls): |
| 165 | + if rind == 0: |
| 166 | + wdh = 14 |
| 167 | + elif rind == 1: |
| 168 | + wdh = 75 |
| 169 | + elif rind == 2: |
| 170 | + wdh = 13 |
| 171 | + elif rind == 4 or rind == 3: |
| 172 | + wdh = 11 |
| 173 | + |
| 174 | + if indx == 0: |
| 175 | + pdf.set_font(style="B") |
| 176 | + else: |
| 177 | + pdf.set_font(style="") |
| 178 | + if ir < ls - 1: |
| 179 | + if sem not in stdims: |
| 180 | + stdims[sem] = [] |
| 181 | + stdims[sem] = [pdf.get_x(), pdf.get_y()] |
| 182 | + pdf.set_font(style="BU", size=10) |
| 183 | + pdf.text(x=stdims[sem][0], y=stdims[sem][1] - 1, txt=f"Semester {sem + 1}") |
| 184 | + pdf.set_font(style="") |
| 185 | + pdf.set_xy(x=stdims[sem][0], y=stdims[sem][1]) |
| 186 | + pdf.multi_cell(wdh, line_height, str(info[ir]), border=1, ln=3, max_line_height=pdf.font_size, align="C") |
| 187 | + rind += 1 |
| 188 | + if indx == (len(dfl[roll][sem + 1]) - 1): |
| 189 | + if sem not in dims: |
| 190 | + dims[sem] = [] |
| 191 | + dims[sem] = [pdf.get_x().__round__(2), pdf.get_y().__round__(2)] |
| 192 | + abscissa = pdf.get_x() |
| 193 | + tx = pdf.get_x() |
| 194 | + if (sem + 1) % 3 == 0: |
| 195 | + recy = pdf.get_y() + 22.5 |
| 196 | + abscissa = 7 |
| 197 | + recx = abscissa |
| 198 | + cx, cy = pdf.get_x() - 110, pdf.get_y() + 8 |
| 199 | + pdf.set_font(style="B", size=10) |
| 200 | + pdf.text(x=cx - 12, y= cy + 2, txt=f"Total Credits: {str(swcreds[sem + 1])} Credits cleared: {str(clsCreds[sem + 1])} SPI: {str(spiz[sem + 1])} CPI: {str(cpiz[sem + 1])}") |
| 201 | + pdf.rect(x=cx - 14, y=cy - 2, w=94, h=5.6, style="") |
| 202 | + pdf.set_font(style="", size=9) |
| 203 | + ah = recy if recy > 0 else ordinate |
| 204 | + pdf.set_y(ah) |
| 205 | + ordinate = pdf.get_y() |
| 206 | + indx += 1 |
| 207 | + pdf.ln(line_height) |
| 208 | + else: |
| 209 | + missed += 1 |
| 210 | + continue |
| 211 | + ldims = len(dims) - missed - 1 |
| 212 | + if signAv: |
| 213 | + pdf.image(os.path.join(os.getcwd(), "uploads/sign.jpeg"), x=pdf.w-65, y=dims[ldims][1] + 37, w=40) |
| 214 | + if sealAv: |
| 215 | + pdf.image(os.path.join(os.getcwd(), "uploads/seal.jpeg"), x=(pdf.w - 20)/2, y=dims[ldims][1] + 27, w=40) |
| 216 | + pdf.line(x1=10, y1=dims[ldims][1] + 30, x2= pdf.w - 10, y2=dims[ldims][1] + 28) |
| 217 | + |
| 218 | + xco = dims[ldims][0] + 80 |
| 219 | + yco = dims[ldims][1] + 50 |
| 220 | + pdf.line(xco, yco, xco + 50, yco) |
| 221 | + pdf.set_font(size=14, style="B") |
| 222 | + pdf.text(xco - 42, yco, txt="Assitant Registrar") |
| 223 | + pdf.text(20, yco, txt=f"Date Generated: {datetime.today().strftime('%d-%m-%Y | %H:%M:%S')}") |
| 224 | + pdf.output(f"transcriptsIITP/{roll}.pdf") |
| 225 | + else: |
| 226 | + continue |
| 227 | + return |
| 228 | + |
| 229 | + |
| 230 | +def prepMs(rnz, all=False): |
| 231 | + temp = rnz.replace(" ", "").split("-") |
| 232 | + |
| 233 | + validRange = [] |
| 234 | + absValidRange = [] |
| 235 | + invzRolls = [] |
| 236 | + lulz = False |
| 237 | + |
| 238 | + if not all: |
| 239 | + if len(temp) == 1: |
| 240 | + return False, [] |
| 241 | + |
| 242 | + for f in range(7): |
| 243 | + if temp[1][f] != temp[1][f]: |
| 244 | + lulz = True |
| 245 | + return False, [] |
| 246 | + |
| 247 | + if not lulz: |
| 248 | + start = int(temp[0][-2:]) |
| 249 | + end = int(temp[1][-2:]) + 1 |
| 250 | + |
| 251 | + for num in range(start, end): |
| 252 | + tempo = f"{num}" |
| 253 | + if len(str(num)) == 1: |
| 254 | + tempo = f"0{num}" |
| 255 | + validRange.append(f"{temp[0][:6]}{tempo}") |
| 256 | + |
| 257 | + if os.path.exists(os.path.join(os.getcwd(), "transcriptsIITP")): |
| 258 | + shutil.rmtree(os.path.join(os.getcwd(), "transcriptsIITP")) |
| 259 | + os.mkdir(os.path.join(os.getcwd(), "transcriptsIITP")) |
| 260 | + |
| 261 | + prepLists() |
| 262 | + somethingAns = pd.read_csv(file_to_be_parsed) |
| 263 | + dFrame = pd.read_csv(file_to_be_parsed, usecols=[0, 1, 2, 3, 4, 5], index_col=0) |
| 264 | + dFrame.sort_values(by=["Roll", "Sem", "SubCode"], inplace=True) |
| 265 | + |
| 266 | + cntr = 1 |
| 267 | + |
| 268 | + for index, contents in enumerate(csv.reader(open(subNameMapping))): |
| 269 | + if index > 1: |
| 270 | + for ind in contents: |
| 271 | + dct[contents[0]] = [contents[1], contents[2]] |
| 272 | + |
| 273 | + for index, line in dFrame.iterrows(): |
| 274 | + if index not in dfl: |
| 275 | + dfl[index] = {} |
| 276 | + if line[0] not in dfl[index]: |
| 277 | + dfl[index][line[0]] = [] |
| 278 | + dfl[index][line[0]].append(["Sub", "Course Name", "L-T-P", "CRD", "GRD"]) |
| 279 | + dfl[index][line[0]].append( |
| 280 | + [line[1], dct[line[1]][0], dct[line[1]][1], line[2], line[3]] |
| 281 | + ) |
| 282 | + if all and (rnz.strip(" ") == ""): |
| 283 | + absValidRange.append(index) |
| 284 | + |
| 285 | + if not all: |
| 286 | + for sth in validRange: |
| 287 | + if sth in dfl: |
| 288 | + absValidRange.append(sth) |
| 289 | + else: |
| 290 | + invzRolls.append(sth) |
| 291 | + |
| 292 | + prepPdfForRolls(absValidRange) |
| 293 | + # prepareTranscriptsArchive() |
| 294 | + dfl.clear() |
| 295 | + return True, invzRolls |
| 296 | + |
| 297 | +def prepareTranscriptsArchive(): |
| 298 | + if os.path.exists(os.path.join(os.getcwd(), "transcriptsIITP")): |
| 299 | + if len(os.listdir(os.path.join(os.getcwd(), "transcriptsIITP"))) > 0: |
| 300 | + shutil.make_archive("transcripts", "zip", os.path.join(os.getcwd(), "transcriptsIITP")) |
| 301 | + return True |
| 302 | + return False |
| 303 | + else: |
| 304 | + return False |
| 305 | + |
| 306 | +def main(): |
| 307 | + #prepMs("1901CS01-1901CS04") |
| 308 | + #print("done") |
| 309 | + pass |
| 310 | + |
| 311 | +if __name__ == "__main__": |
| 312 | + main() |
0 commit comments