Spaces:
Sleeping
Sleeping
| """Creative/Design Domain Plugin | |
| Scores creative competency based on: | |
| - Portfolio links (Behance, Dribbble, personal site) | |
| - Project diversity and quality | |
| - Design tool proficiency | |
| - Visual content analysis | |
| """ | |
| import re | |
| import time | |
| import logging | |
| import requests | |
| from typing import Dict, List | |
| from .base_plugin import BaseDomainPlugin, DomainScore | |
| from .plugin_factory import register_plugin | |
| logger = logging.getLogger(__name__) | |
| class CreativePlugin(BaseDomainPlugin): | |
| """Creative/Design domain scoring plugin""" | |
| def __init__(self): | |
| super().__init__() | |
| # Design tools and platforms | |
| self.design_tools = [ | |
| 'figma', 'sketch', 'adobe xd', 'photoshop', 'illustrator', | |
| 'after effects', 'premiere pro', 'blender', 'cinema 4d' | |
| ] | |
| self.portfolio_platforms = ['behance', 'dribbble', 'artstation', 'deviantart'] | |
| def _get_domain_type(self) -> str: | |
| return 'creative' | |
| def _get_feature_weights(self) -> Dict[str, float]: | |
| return { | |
| 'portfolio_quality': 0.35, | |
| 'project_diversity': 0.25, | |
| 'tool_proficiency': 0.20, | |
| 'platform_presence': 0.15, | |
| 'description_depth': 0.05 | |
| } | |
| def get_required_fields(self) -> List[str]: | |
| return ['portfolio_url'] | |
| def get_optional_fields(self) -> List[str]: | |
| return ['behance_url', 'dribbble_url', 'design_tools_text', 'project_description'] | |
| def score(self, evidence_data: Dict) -> DomainScore: | |
| """Calculate creative domain score""" | |
| start_time = time.time() | |
| features = {} | |
| # Portfolio analysis | |
| portfolio_url = evidence_data.get('portfolio_url', '') | |
| if portfolio_url: | |
| features['portfolio_quality'] = self._analyze_portfolio_quality(portfolio_url) | |
| else: | |
| features['portfolio_quality'] = 0.0 | |
| # Platform presence | |
| behance_url = evidence_data.get('behance_url', '') | |
| dribbble_url = evidence_data.get('dribbble_url', '') | |
| features['platform_presence'] = self._check_platform_presence(behance_url, dribbble_url) | |
| # Tool proficiency | |
| tools_text = evidence_data.get('design_tools_text', '') | |
| features['tool_proficiency'] = self._assess_tool_proficiency(tools_text) | |
| # Project diversity and description | |
| project_desc = evidence_data.get('project_description', '') | |
| features['project_diversity'] = self._assess_project_diversity(project_desc) | |
| features['description_depth'] = self._assess_description_depth(project_desc) | |
| # Calculate weighted score | |
| score = sum(features[k] * self.feature_weights[k] for k in features.keys()) | |
| # Calculate confidence | |
| confidence = self.calculate_confidence(evidence_data) | |
| processing_time = (time.time() - start_time) * 1000 | |
| return DomainScore( | |
| domain_type='creative', | |
| score=min(score, 1.0), | |
| confidence=confidence, | |
| raw_features=features, | |
| processing_time_ms=processing_time | |
| ) | |
| def _analyze_portfolio_quality(self, portfolio_url: str) -> float: | |
| """ | |
| Analyze portfolio website quality | |
| Returns: 0-1 score based on accessibility and professionalism | |
| """ | |
| try: | |
| if not portfolio_url.startswith(('http://', 'https://')): | |
| portfolio_url = 'https://' + portfolio_url | |
| response = requests.head(portfolio_url, timeout=5, allow_redirects=True) | |
| if response.status_code == 200: | |
| score = 0.6 # Base score for accessible portfolio | |
| # Bonus for professional platforms | |
| if any(platform in portfolio_url for platform in self.portfolio_platforms): | |
| score += 0.2 | |
| # Bonus for custom domain | |
| if not any(free in portfolio_url for free in ['github.io', 'wixsite', 'wordpress.com']): | |
| score += 0.2 | |
| logger.info(f"Portfolio quality: {score:.2f}") | |
| return min(score, 1.0) | |
| else: | |
| return 0.2 | |
| except Exception as e: | |
| logger.error(f"Error analyzing portfolio: {e}") | |
| return 0.2 | |
| def _check_platform_presence(self, behance_url: str, dribbble_url: str) -> float: | |
| """ | |
| Check presence on design platforms | |
| Returns: 0-1 score based on platform profiles | |
| """ | |
| score = 0.0 | |
| # Behance presence | |
| if behance_url and 'behance.net' in behance_url: | |
| try: | |
| response = requests.head(behance_url, timeout=5, allow_redirects=True) | |
| if response.status_code == 200: | |
| score += 0.5 | |
| except: | |
| score += 0.2 # Partial credit for providing URL | |
| # Dribbble presence | |
| if dribbble_url and 'dribbble.com' in dribbble_url: | |
| try: | |
| response = requests.head(dribbble_url, timeout=5, allow_redirects=True) | |
| if response.status_code == 200: | |
| score += 0.5 | |
| except: | |
| score += 0.2 | |
| logger.info(f"Platform presence: {score:.2f}") | |
| return min(score, 1.0) | |
| def _assess_tool_proficiency(self, tools_text: str) -> float: | |
| """ | |
| Assess design tool proficiency | |
| Returns: 0-1 score based on tool mentions | |
| """ | |
| if not tools_text: | |
| return 0.0 | |
| text_lower = tools_text.lower() | |
| # Count tool mentions | |
| tool_count = sum(1 for tool in self.design_tools if tool in text_lower) | |
| # Score based on tool diversity | |
| score = min(tool_count / 5, 1.0) # 5+ tools = max | |
| # Bonus for professional tools (Adobe, Figma) | |
| pro_tools = ['figma', 'adobe', 'sketch'] | |
| if any(tool in text_lower for tool in pro_tools): | |
| score = min(score + 0.2, 1.0) | |
| logger.info(f"Tool proficiency: {score:.2f} ({tool_count} tools)") | |
| return score | |
| def _assess_project_diversity(self, project_desc: str) -> float: | |
| """ | |
| Assess project type diversity | |
| Returns: 0-1 score based on project variety | |
| """ | |
| if not project_desc: | |
| return 0.0 | |
| text_lower = project_desc.lower() | |
| # Project type categories | |
| project_types = [ | |
| 'ui design', 'ux design', 'branding', 'logo', 'illustration', | |
| 'animation', '3d', 'web design', 'mobile app', 'poster', | |
| 'packaging', 'typography', 'infographic', 'video editing' | |
| ] | |
| type_count = sum(1 for ptype in project_types if ptype in text_lower) | |
| score = min(type_count / 6, 1.0) # 6+ types = max | |
| logger.info(f"Project diversity: {score:.2f} ({type_count} types)") | |
| return score | |
| def _assess_description_depth(self, project_desc: str) -> float: | |
| """ | |
| Assess depth of project descriptions | |
| Returns: 0-1 score based on detail level | |
| """ | |
| if not project_desc or len(project_desc) < 50: | |
| return 0.0 | |
| score = min(len(project_desc) / 1000, 1.0) # 1000+ chars = max | |
| logger.info(f"Description depth: {score:.2f}") | |
| return score | |